/**
 * 说明：存储一些经常使用的js函数
 * 创建时间：2025-04-11
 * 最近一次更新时间：2025-10-24
 */

/**
 * 动态计算并设置根元素(html)的font-size，实现响应式REM布局方案
 * @function rem
 * @param {number} [designWidth=1920] - 设计稿基准宽度（单位：px）
 * @param {number} [windowWidth=1920] - 窗口最大限制宽度（单位：px）
 * @param {number} [num=10] - REM换算基数（通常设为10便于计算）
 * @param {number} [minWidth=null] - 窗口最小限制宽度（单位：px）
 * @throws {Error} 当参数不是有效数字时抛出错误并显示UI通知
 * @description
 * 1. 核心功能：根据窗口宽度动态计算REM值（公式：REM = 窗口宽度 * num / designWidth）
 * 2. 边界控制：
 *    - 实际宽度超过windowWidth时按windowWidth计算
 *    - 实际宽度低于minWidth时按minWidth计算（同时设置body最小宽度）
 * 3. 自动处理：
 *    - 窗口resize/pageshow事件自动重计算
 *    - 动态创建/更新<style>标签注入REM规则
 *    - 设置默认body字体大小为16px（确保DOM加载完成后生效）
 * @example
 * // 设计稿1920px，限制最大宽度2560px，REM基数10，最小宽度1200px
 * rem(1920, 2560, 10, 1200);
 */
function rem(designWidth,windowWidth,num,minWidth){
    if(designWidth && designWidth !== undefined && !isNumber(designWidth)){
        notification({
            title:'参数错误提示',
            message:'错误函数：rem<br/>错误原因：你传入了一个不能转成数字的参数<br/>错误位置：第一个参数',
            type:'error'
        });
        throw new Error('你传入的第一个参数无法转为数字');
    };
    if(windowWidth && windowWidth !== undefined && !isNumber(windowWidth)){
        notification({
            title:'参数错误提示',
            message:'错误函数：rem<br/>错误原因：你传入了一个不能转成数字的参数<br/>错误位置：第二个参数',
            type:'error'
        });
        throw new Error('你传入的第二个参数无法转为数字');
    };
    if(num && num !== undefined && !isNumber(num)){
        notification({
            title:'参数错误提示',
            message:'错误函数：rem<br/>错误原因：你传入了一个不能转成数字的参数<br/>错误位置：第三个参数',
            type:'error'
        });
        throw new Error('你传入的第三个参数无法转为数字');
    };
    if(minWidth && minWidth !== undefined && !isNumber(minWidth)){
        notification({
            title:'参数错误提示',
            message:'错误函数：rem<br/>错误原因：你传入了一个不能转成数字的参数<br/>错误位置：第四个参数',
            type:'error'
        });
        throw new Error('你传入的第四个参数无法转为数字');
    };
    var defaultValue = {
        designWidth:Number(designWidth) || 1920,
        windowWidth:Number(windowWidth) || 1920,
        num:Number(num) || 10,
        minWidth:Number(minWidth) || null
    };
    var remStyle = document.createElement('style');
    var tid = 'land_js_id_001';
    remStyle.id = tid;
    var refreshRem = function(){
        var width = document.documentElement.getBoundingClientRect().width;
        width > defaultValue.windowWidth && (width = defaultValue.windowWidth);
        if(defaultValue.minWidth){
            if(width < defaultValue.minWidth){
                width = defaultValue.minWidth;
                document.body.style.minWidth = defaultValue.minWidth + 'px';
            }
        };
        var rempx = width * defaultValue.num / defaultValue.designWidth;
        remStyle.innerHTML = 'html{font-size: '+rempx+'px;}';
    };
    if(document.getElementById(tid)){
        document.getElementById(tid).parentNode.removeChild(document.getElementById(tid));
    };
    if(document.documentElement.firstElementChild){
        document.documentElement.firstElementChild.appendChild(remStyle);
    }else{
        var wrap = document.createElement('div');
        wrap.appendChild(remStyle);
        document.write(wrap.innerHTML);
        wrap = null;
    };
    refreshRem();
    window.addEventListener('resize',function(){
        refreshRem();
    },false);
    window.addEventListener('pageshow',function(e){
        if(e.persisted){
            refreshRem();
        }
    },300);
    if(document.readyState === 'complete'){
        document.body.style.fontSize = '16px';
    }else{
        document.addEventListener('DOMContentLoaded',function(e){
            document.body.style.fontSize = '16px';
        },false)
    }
};

/**
 * 获取当前页面中所有元素的最大 z-index 值
 * @returns {number} 返回页面中最大的 z-index 值（默认为1）
 */
function getMaxZIndex(){
    var max = 1;
    var elements = document.getElementsByTagName('*');
    Array.from(elements).forEach(function(element){
        var style = getComputedStyle(element);
        var zIndex = style.getPropertyValue('z-index');
        if(zIndex && !isNaN(parseInt(zIndex))){
            max = Math.max(max,parseInt(zIndex))
        }
    });
    return max;
};

/**
 * 生成随机值（数字、字符串或颜色）
 * @param {number} [a=100] - 控制参数（长度/透明度）
 * @param {string|boolean} [b='str'] - 类型标识 
 *    ('num': 数字, 'color': 颜色, 'str': 字符串, true: 数字, false: 字符串, 'guid': guid（直接过滤第一个参数，也就是第一个参数没有用）)
 * @returns {string} 生成的随机值
 * 
 * @example
 * random(10, 'num')    // 生成10位随机数字串
 * random(50, 'color')  // 生成透明度50%的随机RGBA颜色
 * random(8)            // 生成8位随机字母数字串
 */
function random(a,b){
    var num = a || 100;
    var type = b || 'str';
    var generateGUID = function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0,
                v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    };
    var generateRandomNum = function(){
        var num2 = Math.floor(Math.random() * 10);
        var result = [];
        for(var i = 0; i<Number(num) - 1; i++){
            (function(index){
                result.push(parseInt(Math.random() * 10));
            })(i);
        };
        return result.join('') + num2;
    };
    var generateRandomColor = function(){
        if(Number(num) >= 100){
            return "#" + Math.random().toString(16).substring(2,8).padEnd(6,'0');
        }else{
            var a = Math.random().toString(16).substring(2,8).padEnd(6,'0');
            var r = parseInt(a.substring(0,2),16);
            var g = parseInt(a.substring(2,4),16);
            var b = parseInt(a.substring(4,6),16);
            var opacity = Number(num);
            if(num < 0){
                opacity = Math.abs(opacity);
            };
            var alpha = opacity < 1 ? opacity : opacity / 100;
            return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
        }
    };
    var generateRandomString = function(len){
        return len <= 11 ? Math.random().toString(36).substring(2,2 + len).padEnd(len,0) : generateRandomString(11) + generateRandomString(len - 11);
    };
    if (type === 'guid') {
        return generateGUID();
    };
    if(typeof type === 'boolean'){
        return type ? generateRandomNum() : generateRandomString(Number(num));
    }else{
        switch (type){
            case 'num':
                return generateRandomNum();
            case 'color':
                return generateRandomColor();
            default:
                return generateRandomString(Number(num));
        }
    }
};

/**
 * 自定义弹窗组件
 * @param {string|...string} a - 弹窗提示内容(当第二个参数不是函数时，会拼接所有参数)
 * @param {function|string} [b] - 回调函数或附加消息内容
 * @param {string} [c] - 弹窗类型或附加消息内容
 * @param {string} [d] - 弹窗标题或附加消息内容
 * 
 * @example
 * // 常规用法(第二个参数是函数)
 * alert('操作成功', () => {console.log('回调')}, 'success', '提示');
 * 
 * // 拼接消息内容用法(第二个参数不是函数)
 * alert('操作', '成功', '!'); // 消息内容为"操作成功!"
 */
function alert(a,b,c,d){
	// 判断是否为特殊参数情况（null/undefined/空字符串/函数）
	var isSpecialCase = function(x){
		return x === null || x === undefined || x === '' || typeof x === 'function';
	};
    // 处理参数
    var message,callback,type,title;
    // 判断第二个参数是否是函数
    if(isSpecialCase(b)){
        // 原始参数结构
        message = a || ''; 
        callback = b;
        type = c ? String(c).toLowerCase() : 'info';
        title = d || '系统提示'
    }else{
        // 拼接所有参数作为消息内容
        message = '';
        for(var i=0;i<arguments.length;i++){
            if(arguments[i] !== null && arguments[i] !== undefined){
                message += arguments[i];
            }
        };
        callback = null;
        type = 'info';
        title = '系统提示';
    };
    var dialogId = random(10);
    var styleId = random(10);
    var div1 = document.createElement('div');
    var div2 = document.createElement('div');
    var div3 = document.createElement('div');
    var div4 = document.createElement('div');
    var div5 = document.createElement('div');
    var div6 = document.createElement('div');
    var div7 = document.createElement('div');
    var button = document.createElement('button');
    var dialog = document.createElement('dialog');
    var styles = document.createElement('style');
    div1.className = 'alert1' + dialogId;
    div2.className = 'alert2' + dialogId;
    div3.className = 'alert3' + dialogId;
    div4.className = 'alert4' + dialogId;
    div5.className = 'alert5' + dialogId;
    div6.className = 'alert6' + dialogId;
    div7.className = 'alert7' + dialogId;
    button.className = 'alert8' + dialogId;
    dialog.className = 'alert9' + dialogId;
    var styleHtml = '';
    styleHtml += '.alert1' + dialogId + '{width: 420px;height: auto;min-height: 160px;padding: 24px;box-sizing: border-box;background-color: #ffffff;box-shadow: 0 0 10px rgba(0,0,0,0.1);position: fixed;top: 50%;left: 50%;transform: translate(-50%,-50%);border-radius: 4px;}';
    styleHtml += '.alert2' + dialogId + '{display: flex;flex-direction: row;justify-content: flex-start;align-items: center;padding-top: 16px;box-sizing: border-box;width: 100%;height: 40px;}';
    styleHtml += '.alert3' + dialogId + '{width: 21px;height: 21px;margin: 0 13.5px;border-radius: 50%;line-height: 21px;text-align: center;font-weight: bold;color: #ffffff;background-color: '+(type === 'success'?'#27C777':type === 'info'?'#326FF1':type === 'error'?'#F54A45':'#FAC022')+';position: relative;}';
    styleHtml += '.alert3' + dialogId + ' svg{position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);}';
    styleHtml += '.alert4' + dialogId + '{font-size: 16px;color: #262A30;}';
    styleHtml += '.alert5' + dialogId + '{width: 100%;height: auto;min-height: 36px;margin-top: 4px;padding-left: 48px;box-sizing: border-box;}';
    styleHtml += '.alert6' + dialogId + '{line-height: 20px;font-size: 14px;color: #5C626B;}';
    styleHtml += '.alert7' + dialogId + '{display: flex;flex-direction: row;justify-content: flex-end;align-items: center;}';
    styleHtml += '.alert8' + dialogId + '{outline: none;border: none;background-color: #326FF1;width: 74px;height: 32px;text-align: center;line-height: 32px;color: #ffffff;font-size: 14px;border-radius: 6px;cursor: pointer;}';
    styleHtml += '.alert9' + dialogId + '{width: 100%;height: 100%;border: none;background-color: transparent;padding: 0;margin: 0;outline: none;min-width: 100vw;min-height: 100vh;}';
    styleHtml += '.alert9' + dialogId + '::backdrop{background-color: rgba(0,0,0,0.5);backdrop-filter: blur(5px);}';
    var svg = '';
    if(type === 'success'){
        svg = '<svg t="1744276132617" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2658" width="16" height="16"><path d="M887.904 298.208c-12.864-12.064-33.152-11.488-45.216 1.408L415.936 753.984l-233.12-229.696C170.208 511.872 149.952 512 137.536 524.608c-12.416 12.576-12.256 32.864 0.352 45.248l256.48 252.672c0.096 0.096 0.224 0.128 0.32 0.224 0.096 0.096 0.128 0.224 0.224 0.32 2.016 1.92 4.448 3.008 6.784 4.288 1.152 0.672 2.144 1.664 3.36 2.144 3.776 1.472 7.776 2.24 11.744 2.24 4.192 0 8.384-0.832 12.288-2.496 1.312-0.544 2.336-1.664 3.552-2.368 2.4-1.408 4.896-2.592 6.944-4.672 0.096-0.096 0.128-0.256 0.224-0.352 0.064-0.096 0.192-0.128 0.288-0.224l449.184-478.208C901.44 330.592 900.768 310.336 887.904 298.208z" fill="#ffffff" p-id="2659"></path></svg>'
    }else if(type === 'error'){
        svg = '<svg t="1744276189059" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3638" width="16" height="16"><path d="M220.8 812.8l22.4 22.4 272-272 272 272 48-44.8-275.2-272 275.2-272-48-48-272 275.2-272-275.2-22.4 25.6-22.4 22.4 272 272-272 272z" fill="#ffffff" p-id="3639"></path></svg>'
    }else if(type === 'info'){
        svg = '<svg t="1744277506525" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9253" width="16" height="16"><path d="M512 256c36.266667 0 64-27.733333 64-64s-27.733333-64-64-64-64 27.733333-64 64S475.733333 256 512 256zM512 341.333333c-36.266667 0-64 27.733333-64 64l0 426.666667c0 36.266667 27.733333 64 64 64s64-27.733333 64-64L576 405.333333C576 369.066667 548.266667 341.333333 512 341.333333z" p-id="9254" fill="#ffffff"></path></svg>'
    }else if(type === 'warning'){
        svg = '<svg t="1744277544653" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10274" width="16" height="16"><path d="M468.114286 621.714286c7.314286 21.942857 21.942857 36.571429 43.885714 36.571428s36.571429-14.628571 43.885714-36.571428L585.142857 219.428571c0-43.885714-36.571429-73.142857-73.142857-73.142857-43.885714 0-73.142857 36.571429-73.142857 80.457143l29.257143 394.971429zM512 731.428571c-43.885714 0-73.142857 29.257143-73.142857 73.142858s29.257143 73.142857 73.142857 73.142857 73.142857-29.257143 73.142857-73.142857-29.257143-73.142857-73.142857-73.142858z" p-id="10275" fill="#ffffff"></path></svg>'
    };
    div3.innerHTML = svg;
    div4.innerHTML = title;
    div6.innerHTML = message;
    button.innerHTML = '我知道了';
    dialog.id = dialogId;
    div2.appendChild(div3);
    div2.appendChild(div4);
    div5.appendChild(div6);
    div7.appendChild(button);
    div1.appendChild(div2);
    div1.appendChild(div5);
    div1.appendChild(div7);
    dialog.appendChild(div1);
    styles.innerHTML = styleHtml;
    styles.id = styleId;
    document.head.appendChild(styles);
    document.body.appendChild(dialog);
    dialog.showModal();
	// dialog.addEventListener('click',function(event){
	// 	if(event.target === dialog){
	// 		dialog.close();
	// 	}
	// });
    button.addEventListener('click',function(event){
        dialog.close();
        if(document.getElementById(dialogId)){
            document.getElementById(dialogId).parentNode.removeChild(document.getElementById(dialogId));
        };
        if(document.getElementById(styleId)){
            document.getElementById(styleId).parentNode.removeChild(document.getElementById(styleId));
        };
        if(callback){
            callback();
        };
        event.stopPropagation();
    })
};

/**
 * 显示一个全局通知消息
 * @param {Object} obj - 配置对象
 * @param {string} [obj.position='right-top'] - 通知位置 (right-top/right-bottom/left-top/left-bottom)
 * @param {string} [obj.title='通知'] - 通知标题
 * @param {string} [obj.message=''] - 通知内容
 * @param {string} [obj.type='info'] - 通知类型 (info/success/error/warning)
 * @param {number} [obj.duration=5000] - 自动关闭延时(毫秒)
 * @param {function} [obj.callback=null] - 关闭后的回调
 * 
 * @example
 * // 显示一个5秒后自动关闭的成功通知
 * notification({
 *   title: '操作成功',
 *   message: '您的订单已提交',
 *   type: 'success',
 *   duration: 5000
 * });
 * 
 * // 显示一个右下角的警告通知
 * notification({
 *   position: 'right-bottom',
 *   title: '警告',
 *   message: '磁盘空间不足',
 *   type: 'warning'
 * });
 */
function notification(obj){
    var divId1 = 'land_js_id_002';
    var divId2 = random(10);
    var defaultInfo = {
        position:obj.position || 'right-top',
        title:obj.title || '通知',
        message:obj.message || '',
        type:obj.type?obj.type.toLowerCase():'info',
        duration:obj.duration || 5000,
        callback:obj.callback || null
    };
    var div1 = document.createElement('div');
    var div2 = document.createElement('div');
    var div3 = document.createElement('div');
    var div4 = document.createElement('div');
    var div5 = document.createElement('div');
    var div6 = document.createElement('div');
    var inHML = '';
    var isType = '';
    div1.id = divId1;
    div1.style.cssText = 'position: fixed;max-height: 100%;z-index: '+(getMaxZIndex() + 1)+';';
    switch (defaultInfo.position){
        case 'right-top':
            div1.style.cssText += 'top:16px;right:16px;';
            break;
        case 'right-bottom':
            div1.style.cssText += 'bottom:16px;right:16px;';
            break;
        case 'left-top':
            div1.style.cssText += 'left:16px;top:16px;';
            break;
        case 'left-bottom':
            div1.style.cssText += 'left:16px;bottom:16px;';
            break;
    };
    div2.style.cssText = 'width: 330px;padding: 14px 26px 14px 13px;background-color: #ffffff;border-radius: 8px;margin-bottom: 16px;position: relative;box-shadow: 0 0 16px rgba(0,0,0,0.15);box-sizing: border-box;opacity: 1;transition: height 0.5s ease-in,opacity 0.5s ease-in,padding 0.5s ease-in,margin-bottom 0.5s ease-in;overflow: hidden;';
    div2.id = divId2;
    div3.style.cssText = 'display: flex;flex-direction: row;font-size: 16px;';
    switch (defaultInfo.type){
        case 'info':
            isType = '#326FF1';
            inHML = '<svg style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);" t="1744277506525" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9253" width="16" height="16"><path d="M512 256c36.266667 0 64-27.733333 64-64s-27.733333-64-64-64-64 27.733333-64 64S475.733333 256 512 256zM512 341.333333c-36.266667 0-64 27.733333-64 64l0 426.666667c0 36.266667 27.733333 64 64 64s64-27.733333 64-64L576 405.333333C576 369.066667 548.266667 341.333333 512 341.333333z" p-id="9254" fill="#ffffff"></path></svg>';
            break;
        case 'success':
            isType = '#27C777';
            inHML = '<svg style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);" t="1744276132617" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2658" width="16" height="16"><path d="M887.904 298.208c-12.864-12.064-33.152-11.488-45.216 1.408L415.936 753.984l-233.12-229.696C170.208 511.872 149.952 512 137.536 524.608c-12.416 12.576-12.256 32.864 0.352 45.248l256.48 252.672c0.096 0.096 0.224 0.128 0.32 0.224 0.096 0.096 0.128 0.224 0.224 0.32 2.016 1.92 4.448 3.008 6.784 4.288 1.152 0.672 2.144 1.664 3.36 2.144 3.776 1.472 7.776 2.24 11.744 2.24 4.192 0 8.384-0.832 12.288-2.496 1.312-0.544 2.336-1.664 3.552-2.368 2.4-1.408 4.896-2.592 6.944-4.672 0.096-0.096 0.128-0.256 0.224-0.352 0.064-0.096 0.192-0.128 0.288-0.224l449.184-478.208C901.44 330.592 900.768 310.336 887.904 298.208z" fill="#ffffff" p-id="2659"></path></svg>';
            break;
        case 'error':
            isType = '#F54A45';
            inHML = '<svg style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);" t="1744276189059" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3638" width="16" height="16"><path d="M220.8 812.8l22.4 22.4 272-272 272 272 48-44.8-275.2-272 275.2-272-48-48-272 275.2-272-275.2-22.4 25.6-22.4 22.4 272 272-272 272z" fill="#ffffff" p-id="3639"></path></svg>';
            break;
        case 'warning':
            isType = '#FAC022';
            inHML = '<svg style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);" t="1744277544653" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10274" width="16" height="16"><path d="M468.114286 621.714286c7.314286 21.942857 21.942857 36.571429 43.885714 36.571428s36.571429-14.628571 43.885714-36.571428L585.142857 219.428571c0-43.885714-36.571429-73.142857-73.142857-73.142857-43.885714 0-73.142857 36.571429-73.142857 80.457143l29.257143 394.971429zM512 731.428571c-43.885714 0-73.142857 29.257143-73.142857 73.142858s29.257143 73.142857 73.142857 73.142857 73.142857-29.257143 73.142857-73.142857-29.257143-73.142857-73.142857-73.142858z" p-id="10275" fill="#ffffff"></path></svg>';
            break;
    };
    div4.style.cssText = 'width: 21px;height: 21px;border-radius: 50%;background-color: '+isType+';position: relative;';
    div4.innerHTML = inHML;
    div5.style.cssText = 'font-weight: 700;color: #333333;margin-left: 10px;';
    div5.innerHTML = defaultInfo.title;
    div6.style.cssText = 'text-indent: 24px;font-size: 16px;color: #333333;margin-top: 10px;line-height: 24px;';
    div6.innerHTML = defaultInfo.message;
    div3.appendChild(div4);
    div3.appendChild(div5);
    div2.appendChild(div3);
    div2.appendChild(div6);
    if(document.getElementById(divId1)){
        if(defaultInfo.position === 'right-bottom' || defaultInfo.position === 'left-bottom'){
            document.getElementById(divId1).insertBefore(div2,document.getElementById(divId1).firstChild);
        }else{
            document.getElementById(divId1).appendChild(div2);
        }
    }else{
        div1.appendChild(div2);
        document.body.appendChild(div1);
    };
    var removeDiv = function(){
        var length = document.getElementById(divId1).childNodes.length;
        if(length === 0){
            document.getElementById(divId1).parentNode.removeChild(document.getElementById(divId1));
        }
    };
    var heightDiv2=function(id){
        document.getElementById(id).style.height = document.getElementById(id).clientHeight + 'px';
        setTimeout(function(){
            document.getElementById(id).style.height = '0px';
            document.getElementById(id).style.opacity = 0;
            document.getElementById(id).style.padding = '0 26px 0 13px';
            document.getElementById(id).style.marginBottom = 0;
            setTimeout(function(){
                document.getElementById(id).parentNode.removeChild(document.getElementById(id));
                removeDiv();
                if(defaultInfo.callback && typeof defaultInfo.callback === 'function') {
                    defaultInfo.callback();
                }
            },500);
        },Number(defaultInfo.duration));
    };
    heightDiv2(divId2);
}

/**
 * 判断是否为数字
 * @param {*} input 任意类型
 * @returns {boolean} 如果是数字返回true,否则返回false
 */
function isNumber(input){
    // 检查类型是否为number，注意NaN也是number类型需要排除
    if(typeof input === 'number'){
        return !isNaN(input);
    };
    // 检查是否为数字字符串（包括科学计数法、十六进制、八进制等）
    if(typeof input === 'string'){
        // 去除首尾空格
        var str = input.trim();
        // 空字符串不是数字
        if(!str) return false;
        // 使用Number转换并且检查是否为NaN
        return !isNaN(Number(str));
    };
    return false;
};

/**
 * 发送 AJAX 请求
 * @param {string} [type='GET'] - 请求方法类型，默认为 GET（支持 GET/POST）
 * @param {string} src - 请求的 URL 地址（必填）
 * @param {Object} [params=null] - 请求参数对象（可选）
 * @param {Object} [options={}] - 设置请求头
 * @returns {Promise} 返回一个 Promise 对象，成功时返回响应文本，失败时返回状态码
 * @example
 * // GET 请求示例
 * ajax('GET', '/api/data', {id: 1}).then(res => console.log(res))
 * 
 * // POST 请求示例
 * ajax('POST', '/api/save', {name: '张三'}).then(res => console.log(res))
 */
function ajax(type, src, params, options = {}) {
    var methods = type ? type.toUpperCase() : 'GET';
    var url = src || '';
    var data = params || null;
    
    if (!url || url === '') {
        notification({
            title: 'ajax参数错误',
            message: 'src，第二个参数必传',
            type: 'error'
        });
        return Promise.reject(new Error('URL不能为空'));
    };
    
    if (url.endsWith(".json")) {
        return fetch(url, {
            headers: options.headers || {}
        }).then(function(response) {
            if (!response.ok) {
                throw new Error('网络请求错误');
            };
            return response.json();
        });
    };
    
    return new Promise(function(resolve, reject) {
        var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
        xhr.open(methods, url, true);
        
        // 添加headers支持
        if (options.headers) {
            for (const [key, value] of Object.entries(options.headers)) {
                xhr.setRequestHeader(key, value);
            }
        }
        
        if (methods === 'POST') {
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.send(JSON.stringify(data));
        } else {
            xhr.send(null);
        };
        
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                // 首先检查Content-Type
                const contentType = xhr.getResponseHeader('Content-Type');
                
                // 如果不是JSON响应，直接返回文本
                if (!contentType || !contentType.includes('application/json')) {
                    if (xhr.status === 200 || xhr.status === 201) {
                        return resolve(xhr.responseText);
                    }
                    return reject({
                        status: xhr.status,
                        message: xhr.statusText,
                        response: xhr.responseText
                    });
                }
                
                // 尝试解析JSON
                try {
                    const response = xhr.responseText ? JSON.parse(xhr.responseText) : null;
                    if (xhr.status === 200 || xhr.status === 201) {
                        resolve(response);
                    } else {
                        reject(response || { 
                            status: xhr.status,
                            message: xhr.statusText 
                        });
                    }
                } catch (e) {
                    reject({
                        status: xhr.status,
                        message: '响应解析失败',
                        response: xhr.responseText
                    });
                }
            }
        };
        
        xhr.onerror = function() {
            reject({
                status: 0,
                message: '网络错误'
            });
        };
    });
};

/**
 * Cookie 操作函数（设置、获取、删除）
 * @param {string} code - 操作类型：'get'（获取）、'set'（设置）、'delete'（删除）
 * @param {string} str - Cookie 的名称
 * @param {string} [data] - 可选，Cookie 的值（仅 'set' 时需传入）
 * @param {number} [time] - 可选，Cookie 的过期天数（默认 1 天，仅 'set' 时生效）
 * @example
 * // 设置cookie
 * cookie('set','name','张三',1);
 * // 获取cookie
 * cookie('get','name');
 * // 删除cookie
 * cookie('delete','name');
 */
function cookie(code, str, data, time) {
    var type = code ? code.toLowerCase() : '';
    if (type !== 'get' && type !== 'set' && type !== 'delete') {
        notification({
            title: 'cookie参数错误提示',
            message: '第一个参数取值范围：【get，set，delete】',
            type: 'error'
        });
        return;
    };
    
    var setCookie = function(name, value, days) {
        var expires = '';
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = '; expires=' + date.toUTCString();
        };
        document.cookie = name + '=' + encodeURIComponent(value) + expires + "; path=/";
    };
    
    var getCookie = function(name) {
        var nameEQ = name + '=';
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie1 = cookies[i];
            while (cookie1.charAt(0) === ' ') {
                cookie1 = cookie1.substring(1, cookie1.length);
            };
            if (cookie1.indexOf(nameEQ) === 0) {
                return decodeURIComponent(cookie1.substring(nameEQ.length, cookie1.length));
            }
        };
        return null;
    };
    
    if (type === 'set') {
        var days = time || 1;
        var value = data || '';
        var currentValue = getCookie(str);
        if (currentValue === null || currentValue !== value) {
            setCookie(str, value, days);
        }
    };
    
    if (type === 'get') {
        return getCookie(str);
    };
    
    if (type === 'delete') {
        document.cookie = str + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
    }
};

/**
 * 深拷贝函数（支持对象、数组、Date、RegExp 及循环引用）
 * @param {*} params - 需要拷贝的目标值（任意类型）
 * @param {WeakMap} [defaultValue] - 可选，用于处理循环引用的 WeakMap（内部递归使用，无需手动传入）
 * @returns {*} 深拷贝后的新对象或原始值（若无需拷贝）
 */
function deepClone(params,defaultValue){
    var obj = params || {};
    var hash = defaultValue || new WeakMap();
    if(obj === null) return null;
    if(obj instanceof Date) return new Date(obj);
    if(obj instanceof RegExp) return new RegExp(obj);
    if(typeof obj !== 'object') return obj;
    if(hash.has(obj)) return hash.get(obj);
    var cloneObj = new obj.constructor();
    hash.set(obj,cloneObj);
    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            cloneObj[key] = deepClone(obj[key],hash);
        }
    };
    return cloneObj;
};

/**
 * 深度合并多个对象（支持循环引用检测）
 * @param {...Object} objs - 要合并的对象（多个）
 * @returns {Object} 合并后的新对象
 * @description
 * 1. 递归合并对象的可枚举属性（包括嵌套对象）
 * 2. 自动检测并处理循环引用，避免堆栈溢出
 * 3. 合并策略：
 *    - 普通对象：递归深度合并
 *    - 数组：合并（拼接）而非覆盖
 *    - Map/Set：合并内容
 *    - Date/RegExp等特殊对象：深拷贝覆盖
 *    - 其他类型：直接覆盖
 * 4. 支持Symbol属性和原型链继承
 */
function deepMerge(...objs) {
    // 处理空参数的情况
    if (objs.length === 0) return {};
    if (objs.length === 1) return deepClone(objs[0]);
    const seen = new WeakMap();
    // 判断是否为普通对象（非数组、非null）
    const isPlainObject = (item) => {
        return item !== null && typeof item === 'object' && !Array.isArray(item) && 
               !(item instanceof Date) && !(item instanceof RegExp) && 
               !(item instanceof Map) && !(item instanceof Set);
    };
    // 深度克隆辅助函数（用于初始复制）
    const deepClone = (obj, hash = new WeakMap()) => {
        if (obj === null) return null;
        if (typeof obj !== 'object') return obj;
        if (obj instanceof Date) return new Date(obj);
        if (obj instanceof RegExp) return new RegExp(obj);
        if (hash.has(obj)) return hash.get(obj);
        if (obj instanceof Map) {
            const clone = new Map();
            hash.set(obj, clone);
            obj.forEach((value, key) => {
                clone.set(deepClone(key, hash), deepClone(value, hash));
            });
            return clone;
        }
        if (obj instanceof Set) {
            const clone = new Set();
            hash.set(obj, clone);
            obj.forEach(value => {
                clone.add(deepClone(value, hash));
            });
            return clone;
        }
        const cloneObj = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj));
        hash.set(obj, cloneObj);
        
        // 克隆所有属性（包括Symbol属性）
        const allKeys = [...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)];
        for (const key of allKeys) {
            if (obj.propertyIsEnumerable(key)) {
                cloneObj[key] = deepClone(obj[key], hash);
            }
        }
        return cloneObj;
    };
    // 核心合并逻辑
    const merge = (target, source) => {
        if (seen.has(source)) {
            return seen.get(source);
        }
        seen.set(source, target);
        // 获取所有可枚举属性（包括Symbol）
        const sourceKeys = [...Object.getOwnPropertyNames(source), ...Object.getOwnPropertySymbols(source)];
        for (const key of sourceKeys) {
            if (!source.propertyIsEnumerable(key)) continue;
            const sourceValue = source[key];
            const targetValue = target[key];
            // 处理循环引用
            if (seen.has(sourceValue)) {
                target[key] = seen.get(sourceValue);
                continue;
            }
            // 数组合并策略：可以选择覆盖或合并，这里选择合并
            if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
                target[key] = [...targetValue, ...sourceValue.map(item => 
                    isPlainObject(item) || Array.isArray(item) ? deepClone(item) : item
                )];
            }
            // Map合并
            else if (targetValue instanceof Map && sourceValue instanceof Map) {
                sourceValue.forEach((value, mapKey) => {
                    targetValue.set(
                        deepClone(mapKey), 
                        deepClone(value)
                    );
                });
            }
            // Set合并
            else if (targetValue instanceof Set && sourceValue instanceof Set) {
                sourceValue.forEach(value => {
                    targetValue.add(deepClone(value));
                });
            }
            // 普通对象深度合并
            else if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
                merge(targetValue, sourceValue);
            }
            // 日期、正则等特殊对象直接覆盖
            else if (sourceValue instanceof Date || sourceValue instanceof RegExp) {
                target[key] = deepClone(sourceValue);
            }
            // 其他情况直接覆盖
            else {
                target[key] = deepClone(sourceValue);
            }
        }
        return target;
    };
    // 创建初始结果的深拷贝
    let result = deepClone(objs[0]);
    seen.set(objs[0], result);
    // 合并剩余对象
    for (let i = 1; i < objs.length; i++) {
        if (objs[i] !== null && typeof objs[i] === 'object') {
            merge(result, objs[i]);
        }
    }
    return result;
};

/**
 * 数字/字符串填充函数（支持前导补位或后导补位）
 * @param {number|string} num - 需要填充的目标值（数字或字符串）
 * @param {number} n - 填充后的总长度
 * @param {string} str - 用于填充的字符（通常为单个字符，如 '0'、' '）
 * @param {boolean} [code=false] - 可选，填充模式：
 *   - true:  前导补位（在开头填充）
 *   - false: 后导补位（在末尾填充，默认）
 * @returns {string} 填充后的字符串
 * @example
 * ez(5, 3, '0')       // 返回 "005"（后导补位）
 * ez(5, 3, '0', true) // 返回 "500"（前导补位）
 */
function ez(num,n,str,code){
    var type = code || false;
    var targetStr = String(num);
    if(targetStr.length >= n){
        return targetStr;
    };
    var padLength = n - targetStr.length;
    var padStr = str.repeat(padLength).slice(0,padLength);
    return type ? padStr + targetStr : targetStr + padStr;
};

/**
 * 字体样式操作工具函数
 * @param {string} [selector] - CSS选择器，可选。若不传则默认选择所有元素('*')
 * @returns {Object} 返回包含多个方法的字体操作对象
 * @example
 * fonts('div').size(1.2).color('#ff0000');
 */
function fonts(selector){
    var fontObj = {};
    fontObj.elements = typeof selector === 'string' ? document.querySelectorAll(selector) : document.querySelectorAll('*');
    fontObj.unit = 'px';
    fontObj.initialFontSize = new WeakMap();
    fontObj.lastSize = null;
    var initializeInitialFontSize = function(){
        Array.prototype.forEach.call(fontObj.elements,function(element){
            if(!fontObj.initialFontSize.has(element)){
                var currentFontSize = window.getComputedStyle(element).fontSize;
                fontObj.initialFontSize.set(element,parseFloat(currentFontSize));
            }
        })
    };
    var applySize = function(){
        if(!fontObj.lastSize) return;
        initializeInitialFontSize();
        Array.prototype.forEach.call(fontObj.elements,function(element){
            var initialFontSize = fontObj.initialFontSize.get(element);
            var newFontSize = Math.round(initialFontSize * Number(fontObj.lastSize));
            element.style.fontSize = newFontSize + fontObj.unit;
        });
    };
    fontObj.size = function(multiplier){
        if(multiplier && !isNaN(Number(multiplier))){
            initializeInitialFontSize();
            fontObj.lastSize = multiplier;
            applySize();
        };
        return this;
    };
    fontObj.color = function(color){
        if(color){
            Array.prototype.forEach.call(fontObj.elements,function(element){
                element.style.color = color;
            });
        };
        return this;
    };
    fontObj.set = function(unit){
        if(unit){
            fontObj.unit = unit;
            applySize();
        };
        return this;
    };
    return fontObj;
};

/**
 * 从当前URL的查询参数中获取指定参数值或全部参数对象
 * @function getSearchString
 * @param {string} [params=""] - 需要获取的查询参数键名（可选）。若留空则返回全部参数对象
 * @returns {(string|object|null)} - 返回结果取决于输入参数：
 *   - 当params为空时：返回包含所有查询参数的键值对对象
 *   - 当params有值时：返回对应参数值（若不存在则返回null并显示通知）
 * @example
 * // 示例URL: http://example.com?name=张三&age=20
 * getSearchString();      // 返回: {name: "张三", age: "20"}
 * getSearchString("age"); // 返回: "20"
 * getSearchString("sex"); // 返回: null
 * @description
 * 1. 解析当前窗口URL的search部分（问号后的查询字符串）
 * 2. 将查询字符串转换为参数键值对对象
 * 3. 对参数名和值都执行decodeURIComponent解码
 */
function getSearchString(params) {
    var key = params || "";
    var url = window.location.search;
    var obj = {};
    if (url) {
        var str = url.substring(1);
        var arr = str.split('&');
        for (var i = 0; i < arr.length; i++) {
            var paramPair = arr[i].split('=');
            var paramName = decodeURIComponent(paramPair[0] || "");
            var paramValue = decodeURIComponent(paramPair[1] || "");
            if (paramName) {
                obj[paramName] = paramValue;
            }
        }
    }
    if (key === "") {
        return obj;
    } else {
        if (obj[key] === undefined || obj[key] === "") {
            return null;
        } else {
            return obj[key];
        }
    }
};

/**
 * 颜色格式转换工具（HEX和RGBA互转）
 * @param {string} color - 颜色值，支持 #RGB/#RRGGBB 或 rgba(r,g,b,a)
 * @param {number} [opacity=1] - 透明度（0-1）
 * @returns {string} 转换后的颜色值
 * 
 * // 示例：
 * hexRGBA("#f00") => "rgba(255,0,0,1)"
 * hexRGBA("rgba(255,0,0,0.5)") => "#ff0000"
 */
function hexRGBA(params,opacity){
    var color =params || '';
    var alpha = isNaN(Number(opacity))?1:Number(opacity);
    var colors = '';
    if(color === ''){
        return;
    };
    var detectColorType = function(color){
        if (/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),?\s*(0|1|0\.\d+)?\)$/i.test(color)){
            return "RGBA";
        }else if(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/i.test(color)){
            return "HEX";
        }else{
            return "Color Name";
        }
    };
    var convertRGBAToHex = function(rgba){
        var [r,g,b]=rgba.replace(/^rgba?\(|\s+|\)$/g, '').split(',').slice(0,3).map(Number);
        var hex = "#" + (r >> 16).toString().padStart(2,'0') + (g >> 16).toString().padStart(2,'0') + (b >> 16).toString().padStart(2,'0');
        return hex;
    };
    var convertHexToHex = function(hex){
        if(hex.length===4){
            hex = "#" + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
        };
        const r = parseInt(hex.slice(1, 3), 16);
        const g = parseInt(hex.slice(3, 5), 16);
        const b = parseInt(hex.slice(5, 7), 16);
        return 'rgba('+r+','+g+','+b+','+alpha+')';
    };
    switch (detectColorType(color)){
        case 'RGBA':
            colors = convertRGBAToHex(color);
            break;
        case 'HEX':
            colors = convertHexToHex(color);
            break;
        default:
            notification({
                title:"hexRGBA参数提示",
                message:'函数 hexRGBA 不支持颜色名称转换',
                type:'error'
            })
    };
    return colors;
};

/**
 * 检查字符串是否为有效路径格式
 * @param {string} path - 要检查的路径字符串
 * @returns {boolean} 返回true表示是有效路径，false表示无效
 * @description
 * 支持检查两种路径格式：
 * 1. 本地路径：以/开头，可包含字母、数字、下划线和连字符（如 /user/profile）
 * 2. URL路径：http/https协议开头的网址（如 https://example.com/path）
 * 
 * @example
 * isPath('/user/profile') // true
 * isPath('https://example.com') // true
 * isPath('invalid path') // false
 * isPath('') // 显示错误提示并返回false
 */
function isPath(params) {
    var str = params || '';
	if (str === '') {
		notification({
			title: 'isPath提示',
			message: '参数不能为空！',
			type: 'error',
		});
		return false;
	}
	var pathRegex = /^(\/[\w-]+)+\/?|^(http|https):\/\/[\w-.]+\.[\w-./?%&=]*$/;
	return pathRegex.test(str);
};

/**
 * 格式化数字字符串，添加千位分隔符
 * @param {string|number} value - 要格式化的数字或字符串
 * @returns {string} 格式化后的字符串（带千位分隔符）
 * @description
 * 1. 处理整数和小数（如 1234567.89 → 1,234,567.89）
 * 2. 支持负数（如 -1234567 → -1,234,567）
 * 3. 空值会触发错误提示
 * 
 * @example
 * numberString(1234567) // "1,234,567"
 * numberString("-1234567.89") // "-1,234,567.89"
 * numberString("") // 显示错误提示并返回undefined
 */
function numberString(value){
    var str = value || '';
    if(str === ''){
        notification({
			title: 'numberString提示',
			message: '参数必传',
			type: 'warning',
		});
		return;
    };
    str = String(str).trim();
    if(str === "" || isNaN(Number(str))) {
        notification({
			title: 'numberString提示',
			message: '参数必须是有效数字',
			type: 'warning',
		});
		return;
    };
    var isNegative = str.startsWith('-');
    if(isNegative) {
        str = str.substring(1); // 移除负号临时处理
    }
    var parts = str.split('.');
    var integerPart = parts[0];
    var decimalPart = parts[1] ? '.' + parts[1] : '';
    integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    var result = isNegative ? '-' + integerPart + decimalPart : integerPart + decimalPart;
    return result;
};

/**
 * 全屏切换函数
 * 切换指定元素或整个页面的全屏状态
 * 
 * @param {string} params - 元素选择器，如果为空则对整个文档操作
 * @param {Object} options - 配置选项
 * @param {Function} options.onEnter - 进入全屏回调
 * @param {Function} options.onExit - 退出全屏回调
 * @returns {boolean} 切换后的全屏状态
 * 
 * @example
 * // 切换整个页面全屏
 * screenful();
 * 
 * @example  
 * // 切换指定元素全屏，并设置回调
 * screenful('#video', {
 *     onEnter: function() {
 *         console.log('进入全屏');
 *     },
 *     onExit: function() {
 *         console.log('退出全屏');
 *     }
 * });
 */
function screenful(params, options = {}) {
    var id = params || null;
    var targetElement;
    if(!id) {
        targetElement = document.documentElement;
    } else {
        targetElement = document.querySelector(id);
        if(!targetElement) return;
    };
    const enterFullscreen = function(){
        const requestFunc = targetElement.requestFullscreen || targetElement.webkitRequestFullscreen || targetElement.mozRequestFullScreen || targetElement.msRequestFullscreen;
        if(requestFunc) {
            requestFunc.call(targetElement);
        };
    };
    const exitFullscreen = function(){
        const exitFunc = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
        if(exitFunc){
            exitFunc.call(document);
        }
    };
    const getFullscreenElement = function(){
        return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
    };
    const isFullscreen = !!getFullscreenElement();
    if(isFullscreen){
        exitFullscreen();
        if(options.onExit) options.onExit();
    } else {
        enterFullscreen();
        if(options.onEnter) options.onEnter();
    };
    return !isFullscreen;
};

/**
 * 获取系统时间信息
 * 返回包含各种格式的时间信息对象
 * 
 * @param {string} format - 自定义格式字符串，支持占位符：YYYY-年, MM-月, DD-日, HH-时, mm-分, ss-秒, WW-星期
 * @returns {Object} 包含时间信息的对象
 * 
 * @example
 * // 基础使用 - 不传参数
 * const time = systemTime();
 * console.log(time.YMD);    // "2023-12-15"
 * console.log(time.HMS);    // "14:30:25"
 * console.log(time.full);  // "2023-12-15 14:30:25"
 * console.log(time.Week);   // "星期五"
 * 
 * @example
 * // 格式化使用 - 传入自定义格式
 * const time = systemTime('YYYY年MM月DD日 HH时mm分');
 * console.log(time.full);   // "2023年12月15日 14时30分"
 * console.log(time.YMD);    // "2023年12月15日"
 * console.log(time.HMS);    // "14时30分"
 */
function systemTime(format = null) {
    var now = new Date();
    var Years = now.getFullYear();
    var Month = now.getMonth() + 1;
    var Date = now.getDate();
    var Hours = now.getHours();
    var Minutes = now.getMinutes();
    var Seconds = now.getSeconds();
    var Day = now.getDay();
    var weekDays = ['日', '一', '二', '三', '四', '五', '六'];
    var Week = '星期' + weekDays[Day];
    
    const padZero = (num) => num < 10 ? '0' + num : num.toString();
    
    const formatTime = (template) => {
        if (!template) return template;
        return template.replace('YYYY', Years).replace('MM', padZero(Month)).replace('DD', padZero(Date)).replace('HH', padZero(Hours)).replace('mm', padZero(Minutes)).replace('ss', padZero(Seconds)).replace('WW', Week);
    };
    
    var result = {
        Years: Years,
        Month: padZero(Month),
        Date: padZero(Date),
        Hours: padZero(Hours),
        Minutes: padZero(Minutes),
        Seconds: padZero(Seconds),
        Week: Week,
        timestamp: now.getTime()
    };
    
    const baseFormat = format || 'YYYY-MM-DD';
    result.YMD = formatTime(baseFormat.split(' ')[0]);
    result.HMS = formatTime(baseFormat).replace(/.*?(HH:mm:ss).*?/, '$1');
    result.full = formatTime(baseFormat);
    result.YMDW = formatTime((format ? baseFormat.split(' ')[0] : 'YYYY-MM-DD') + ' WW');
    result.fullW = formatTime((format || 'YYYY-MM-DD HH:mm:ss') + ' WW');
    
    return result;
}
/**
 * 动态创建DOM元素并设置属性和内容
 * @function createTag
 * @param {string} name - 要创建的HTML标签名（如'div'、'a'等）
 * @param {Array<Array<string>>} [att] - 属性键值对数组（可选）
 * @param {string} [html] - 元素内部HTML内容（可选）
 * @returns {HTMLElement} 创建并配置好的DOM元素
 * @description
 * 1. 创建一个指定类型的HTML元素
 * 2. 支持批量设置元素属性（传入二维数组）
 * 3. 支持设置元素内部HTML内容
 * 
 * @example
 * // 创建一个带href属性的链接
 * const link = createTag('a', [['href','https://example.com']], '点击这里');
 * 
 * // 创建一个简单的div
 * const div = createTag('div', null, 'Hello World');
 * 
 * // 创建带多个属性的按钮
 * const btn = createTag('button', [
 *   ['class', 'primary-btn'],
 *   ['id', 'submit-btn'],
 *   ['disabled', 'true']
 * ], '提交');
 */
function createTag(name,att,html){
    var tag = document.createElement(name);
    if(att && att.length > 0){
        for(var i = 0;i < att.length;i++){
            tag.setAttribute(att[i][0],att[i][1]);
        }
    };
    if(html){
        tag.innerHTML = html;
    };
    return tag;
};

/**
 * 创建SVG元素
 * 根据路径数据创建SVG图标
 * 
 * @param {string|Array} pathData - SVG路径数据，可以是字符串或数组
 * @param {string|Array} color - 填充颜色，支持字符串或数组
 * @param {Array} att - 自定义属性数组，格式如 [['width','24'],['height','24']]
 * @returns {SVGElement} 返回创建的SVG元素
 * 
 * @example
 * // 基础使用 - 单路径
 * const svg = createSvg('M512 512m-512 0a512 512 0 1 0 1024 0', '#ff0000');
 * 
 * @example
 * // 多路径多颜色
 * const svg = createSvg(
 *     ['M100 100L200 200', 'M300 300L400 400'],
 *     ['red', 'blue'],
 *     [['width', '24'], ['height', '24']]
 * );
 */
function createSvg(pathData,color,att){
    var svgNS="http://www.w3.org/2000/svg";
    var svg=document.createElementNS(svgNS,'svg');
    svg.setAttribute('viewBox','0 0 1024 1024');
    svg.setAttribute('version','1.1');
    if(att && att.length > 0){
        for(var i = 0;i < att.length;i++){
            console.log(att[i][0], att[i][1]);
            svg.setAttribute(att[i][0],att[i][1]);
        }
    };
	var paths = Array.isArray(pathData) ? pathData : [pathData];
	var colors;
	if(Array.isArray(color)){
		colors = [];
		for(var j=0;j<paths.length;j++){
			colors.push(color[j] || color[0] || 'currentColor');
		}
	}else{
		colors = [];
		var defaultColor = color || 'currentColor';
		for (var k = 0; k < paths.length; k++) {
			colors.push(defaultColor);
		}
	};
	for (var l = 0; l < paths.length; l++) {
		var pathElement = document.createElementNS(svgNS, 'path');
		pathElement.setAttribute('d', paths[l]);
		pathElement.setAttribute('fill', colors[l]);
		svg.appendChild(pathElement);
	}
    return svg;
};


/**
 * 函数节流装饰器，限制函数的执行频率
 * @param {Function} fn - 需要节流的原函数
 * @param {number} [time=500] - 节流时间间隔（毫秒）
 * @param {boolean} [type=true] - 节流模式：true表示立即执行模式，false表示延迟执行模式
 * @returns {Function} - 经过节流处理的新函数
 * 
 * @example
 * // 基本用法
 * const throttledFn = throttle(() => console.log('resized'), 200);
 * window.addEventListener('resize', throttledFn);
 * 
 * @description
 * 该节流函数支持两种模式：
 * 1. 立即执行模式(type=true)：首次调用立即执行，后续在节流时间内只执行最后一次调用
 * 2. 延迟执行模式(type=false)：在节流时间结束后执行最后一次调用
 * 
 * 注意：函数内部使用了闭包变量lastTime和timer来跟踪状态
 */
function throttle(fn,time,type){
    var delay = time || 500;
    var immediate = typeof type === 'undefined'?true:type;
    var lastTime = 0;
    var timer = null;
    return function(...args){
        var context = this;
        var now = Date.now();
        if (immediate && lastTime === 0) {
            fn.apply(context, args);
            lastTime = now;
            return;
        };
        if (now - lastTime < delay) {
            if (timer) {
                clearTimeout(timer);
            };
            timer = setTimeout(function () {
                lastTime = Date.now();
                fn.apply(context, args);
            }, delay - (now - lastTime));
        } else {
            lastTime = now;
            fn.apply(context, args);
        }
    }
};

/**
 * 显示一个模态确认对话框
 * 
 * 此函数会创建一个美观的模态对话框，包含标题、消息内容和确认/取消按钮。
 * 用户点击按钮后会触发回调函数并自动移除对话框元素。
 * 
 * @param {string} message - 对话框中显示的主要消息内容
 * @param {Function} callback - 用户点击按钮后的回调函数，接收一个参数:
 *      'confirm' 表示用户点击了确认按钮
 *      'cancel' 表示用户点击了取消按钮
 * @param {string} [title='系统提示'] - 对话框标题(可选)
 * 
 * @example
 * // 显示确认对话框并处理用户选择
 * confirm('确定要删除这条数据吗？', (result) => {
 *     if(result === 'confirm') {
 *         // 用户点击了确认
 *         deleteData();
 *     } else {
 *         // 用户点击了取消
 *         console.log('操作已取消');
 *     }
 * }, '删除确认');
 * 
 * @description
 * 对话框特性:
 * 1. 使用HTML5 dialog元素实现模态效果
 * 2. 包含半透明黑色遮罩层和模糊效果
 * 3. 自适应内容高度
 * 4. 点击按钮后自动清理DOM元素
 * 5. 内置蓝色信息图标
 */
function confirm(message,callback,title){
    var dialogId = random(10);
    var styleId = random(10);
    var dialog = document.createElement('dialog');
    var div1 = document.createElement('div');
    var div2 = document.createElement('div');
    var div3 = document.createElement('div');
    var div4 = document.createElement('div');
    var div5 = document.createElement('div');
    var div6 = document.createElement('div');
    var div7 = document.createElement('div');
    var button1 = document.createElement('button');
    var button2 = document.createElement('button');
    var styles = document.createElement('style');
    dialog.id = dialogId;
    dialog.className = 'confirm1' + dialogId;
    div1.className = 'confirm2' + dialogId;
    div2.className = 'confirm3' + dialogId;
    div3.className = 'confirm4' + dialogId;
    div4.className = 'confirm5' + dialogId;
    div5.className = 'confirm6' + dialogId;
    div6.className = 'confirm7' + dialogId;
    div7.className = 'confirm8' + dialogId;
    button1.className = 'confirm9' + dialogId;
    button2.className = 'confirm10' + dialogId;
    styles.id = styleId;
    var styleHtml = '';
    styleHtml += '.confirm1' + dialogId + '{width: 100%;height: 100%;border: none;background-color: transparent;padding: 0;margin: 0;outline: none;}';
    styleHtml += '.confirm1' + dialogId + '::backdrop{background-color: rgba(0,0,0,0.5);backdrop-filter: blur(5px);}';
    styleHtml += '.confirm2' + dialogId + '{width: 420px;height: auto;min-height: 160px;padding: 24px;box-sizing: border-box;background-color: #ffffff;box-shadow: 0 0 10px rgba(0,0,0,0.1);position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);border-radius: 4px;}';
    styleHtml += '.confirm3' + dialogId + '{display: flex;flex-direction: row;justify-content: flex-start;align-items: center;padding-top: 16px;box-sizing: border-box;width: 100%;height: 40px;}';
    styleHtml += '.confirm4' + dialogId + '{width: 21px;height: 21px;margin: 0 13.5px;background-color: #326FF1;border-radius: 50%;text-align: center;font-weight: bold;color: #ffffff;}';
    styleHtml += '.confirm5' + dialogId + '{font-size: 16px;color: #262A30;}';
    styleHtml += '.confirm6' + dialogId + '{width: 100%;height: auto;min-height: 36px;margin-top: 4px;padding-left: 48px;box-sizing: border-box;}';
    styleHtml += '.confirm7' + dialogId + '{line-height: 20px;font-size: 14px;color: #5C626B;}';
    styleHtml += '.confirm8' + dialogId + '{display: flex;flex-direction: row;justify-content: flex-end;align-items: center;}';
    styleHtml += '.confirm9' + dialogId + '{outline: none;border: none;background-color: #ffffff;width: 74px;height: 32px;text-align: center;line-height: 32px;color: #333333;font-size: 14px;border-radius: 6px;cursor: pointer;border: 1px solid #cbcfd6;}';
    styleHtml += '.confirm10' + dialogId + '{outline: none;border: none;background-color: #326FF1;width: 74px;height: 32px;text-align: center;line-height: 32px;color: #ffffff;font-size: 14px;border-radius: 6px;cursor: pointer;margin-left: 8px;}';
    var svg = '<svg t="1744277506525" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9253" width="16" height="16"><path d="M512 256c36.266667 0 64-27.733333 64-64s-27.733333-64-64-64-64 27.733333-64 64S475.733333 256 512 256zM512 341.333333c-36.266667 0-64 27.733333-64 64l0 426.666667c0 36.266667 27.733333 64 64 64s64-27.733333 64-64L576 405.333333C576 369.066667 548.266667 341.333333 512 341.333333z" p-id="9254" fill="#ffffff"></path></svg>';
    div3.innerHTML = svg;
    div4.textContent = title || '系统提示';
    div6.textContent = message || '';
    button1.textContent = '取消';
    button2.textContent = '确认';
    div2.appendChild(div3);
    div2.appendChild(div4);
    div5.appendChild(div6);
    div7.appendChild(button1);
    div7.appendChild(button2);
    div1.appendChild(div2);
    div1.appendChild(div5);
    div1.appendChild(div7);
    dialog.appendChild(div1);
    styles.innerHTML = styleHtml;
    document.head.appendChild(styles);
    document.body.appendChild(dialog);
    dialog.showModal();
    button1.onclick = function(event){
        event.stopPropagation();
        dialog.close();
        if(document.getElementById(styleId)){
            document.getElementById(styleId).parentNode.removeChild(document.getElementById(styleId));
        };
        if(document.getElementById(dialogId)){
            document.getElementById(dialogId).parentNode.removeChild(document.getElementById(dialogId));
        };
        if(callback){
            callback('cancel');
        }
    };
    button2.onclick = function(event){
        event.stopPropagation();
        dialog.close();
        if(document.getElementById(styleId)){
            document.getElementById(styleId).parentNode.removeChild(document.getElementById(styleId));
        };
        if(document.getElementById(dialogId)){
            document.getElementById(dialogId).parentNode.removeChild(document.getElementById(dialogId));
        };
        if(callback){
            callback('confirm');
        }
    }
};

/**
 * 智能合并多个选项（自动判断合并方式，忽略无效参数）
 * 
 * 规则：
 * 1. 跳过所有非对象/非数组参数，找到第一个有效参数确定类型
 * 2. 如果找到对象，则执行对象合并，忽略后续数组
 * 3. 如果找到数组，则执行数组合并，忽略后续对象
 * 4. 如果全部参数无效，返回null
 * 
 * @param {...(Object|Array)} [options] - 要合并的选项（对象或数组）
 * @returns {Object|Array|null} 合并后的结果
 * 
 * @example
 * // 对象合并（跳过非对象参数）
 * mergeOptions(null, {a:1}, [1,2]) // => {a:1}
 * 
 * @example
 * // 数组合并（跳过非数组参数）
 * mergeOptions(undefined, [1], {b:2}) // => [1]
 * 
 * @example
 * // 全部无效返回null
 * mergeOptions(null, undefined) // => null
 */
function merge() {
    var args = Array.prototype.slice.call(arguments);
    var mergeType = null;
    var firstValidIndex = -1;
    for (var i = 0; i < args.length; i++) {
        var arg = args[i];
        if (Array.isArray(arg)) {
            mergeType = 'array';
            firstValidIndex = i;
            break;
        }
        if (typeof arg === 'object' && arg !== null) {
            mergeType = 'object';
            firstValidIndex = i;
            break;
        }
    }
    if (mergeType === null) return null;
    if (mergeType === 'object') {
        var result = {};
        for (var j = firstValidIndex; j < args.length; j++) {
            var item = args[j];
            if (typeof item === 'object' && item !== null && !Array.isArray(item)) {
                for (var key in item) {
                    if (item.hasOwnProperty(key)) {
                        result[key] = item[key];
                    }
                }
            }
        }
        return result;
    } else {
        var result = [];
        var seen = new Set();
        for (var k = firstValidIndex; k < args.length; k++) {
            var element = args[k];
            if (Array.isArray(element)) {
                for (var m = 0; m < element.length; m++) {
                    var value = element[m];
                    var valueKey = typeof value + JSON.stringify(value);
                    if (!seen.has(valueKey)) {
                        seen.add(valueKey);
                        result.push(value);
                    }
                }
            }
        }
        return result;
    }
}

/**
 * 创建指定滚动效果
 * 为元素创建自动滚动轮播效果，支持上下左右方向
 * 
 * @param {string} selector - CSS选择器
 * @param {string} type - 滚动方向：'top'（上）| 'left'（左）
 * @param {number} time - 滚动间隔时间（毫秒）
 * @param {string} size - 滚动距离
 * @param {number} num - 最小子元素数量
 * @param {string} margin - 边距
 * @param {boolean} lets - 是否启用鼠标交互控制
 * @returns {Object} 返回滚动控制器
 * 
 * @example
 * // 创建垂直滚动
 * const scroller = appointScroll('.news-list', 'top', 3000, '100px', 3, '0px', true);
 * 
 * @example
 * // 创建水平滚动
 * const scroller = appointScroll('.banner', 'left', 2000, '200px', 2, '10px', false);
 * 
 * // 控制方法
 * scroller.stopAll();  // 停止所有滚动
 * scroller.startAll(); // 开始所有滚动
 */
function appointScroll(selector, type, time, size, num, margin, lets) {
    var containers = document.querySelectorAll(selector);
    if (containers.length === 0) return;
    var controllers = [];
    for (var c = 0; c < containers.length; c++) {
        (function(container) {
            var timmerIDJSABC = null;
            var acquiesce = {
                lets: lets || false,
                type: type || 'top',
                time: Number(time) || 5000,
                margin: margin || '0px',
                size: size || '0px',
                num: num || 1
            };
            if (acquiesce.lets && timmerIDJSABC) {
                clearInterval(timmerIDJSABC);
            }
            var childLabel = container.children;
            // 设置子元素样式（保持你原来的逻辑）
            for (var i = 0; i < childLabel.length; i++) {
                var item = childLabel[i];
                if (acquiesce.type === 'top') {
                    item.style.transition = 'margin-top 0.8s';
                }
                if (acquiesce.type === 'left') {
                    item.style.transition = 'margin-left 0.8s';
                    item.style.float = 'left';
                }
            }
            
            // 设置容器宽度（水平滚动时）
            if (acquiesce.type === 'left') {
                container.style.width = (childLabel[0].clientWidth * childLabel.length) + 'px';
            }
            // 滚动函数（保持你原来的逻辑）
            var MhyMar = function() {
                var first = container.firstElementChild;
                switch (acquiesce.type) {
                    case 'left':
                        first.style.marginLeft = acquiesce.margin;
                        first.style.marginLeft = acquiesce.size;
                        break;
                    default:
                        first.style.marginTop = acquiesce.margin;
                        first.style.marginTop = acquiesce.size;
                }
                window.setTimeout(function() {
                    switch (acquiesce.type) {
                        case 'left':
                            first.style.marginLeft = acquiesce.margin;
                            break;
                        default:
                            first.style.marginTop = acquiesce.margin;
                    }
                    container.appendChild(first);
                }, 800);
            };
            // 启动轮播（保持你原来的逻辑）
            if (childLabel.length >= acquiesce.num) {
                timmerIDJSABC = window.setInterval(MhyMar, acquiesce.time);
                if (acquiesce.lets) {
                    container.onmousedown = function() {
                        window.clearInterval(timmerIDJSABC);
                    };
                    container.onmouseover = function() {
                        window.clearInterval(timmerIDJSABC);
                    };
                    container.onmouseout = function() {
                        timmerIDJSABC = window.setInterval(MhyMar, acquiesce.time);
                    };
                }
            }
            // 存储控制器
            controllers.push({
                stop: function() {
                    if (timmerIDJSABC) {
                        clearInterval(timmerIDJSABC);
                        timmerIDJSABC = null;
                    }
                },
                start: function() {
                    if (!timmerIDJSABC && childLabel.length >= acquiesce.num) {
                        timmerIDJSABC = window.setInterval(MhyMar, acquiesce.time);
                    }
                }
            });
            
        })(containers[c]);
    }
    // 返回控制器
    return {
        stopAll: function() {
            controllers.forEach(function(controller) {
                controller.stop();
            });
        },
        startAll: function() {
            controllers.forEach(function(controller) {
                controller.start();
            });
        },
        getInstanceCount: function() {
            return controllers.length;
        }
    };
}

/**
 * 数字动画函数
 * @param { object } options 配置对象
 * @property { number } from 起始数字
 * @property { number } to 目标数字
 * @property { number } duration 动画持续时间（毫秒）
 * @property { function } onUpdate 更新回调函数
 * @property { function } [onComplete] 动画完成回调函数
 * @property { string } [easing='linear'] 缓存函数类型
 * @property { number } [decimals=0] 保留小数位数
 * @returns { Object } 返回包含stop方法的对象
 * 
 * @example
 * // 启动动画
 *  var animation = animateNumber({
 *      from: 0,
 *      to: 1000,
 *      duration: 2000,
 *      decimals: 2,
 *      onUpdate: function(value) {
 *          document.getElementById('counter').innerHTML = value.toFixed(2);
 *      },
 *      onComplete: function() {
 *          alert('动画完成!');
 *      }
 *  });
 *
 *  // 停止按钮事件绑定
 *  var stopBtn = document.getElementById('stopBtn');
 *  if (stopBtn.attachEvent) {
 *      stopBtn.attachEvent('onclick', function() {
 *          animation.stop();
 *      });
 *  } else {
 *      stopBtn.addEventListener('click', function() {
 *          animation.stop();
 *      });
 *  }
 */
function animateNumber(options){
    if(!options || typeof options !== 'object'){
        alert('animateNumber函数报错！Options must be an object');
        throw new Error('Options must be an object');
    };
    var from = options.from !== undefined ? options.from : 0;
    var to = options.to !== undefined ? options.to : 0;
    var duration = options.duration !== undefined ? options.duration : 1000;
    var onUpdate = options.onUpdate;
    var onComplete = options.onComplete;
    var easing = options.easing || 'linear';
    var decimals = options.decimals !== undefined ? options.decimals : 0;
    if(typeof onUpdate !== 'function'){
        alert('animateNumber函数报错！onUpdate must be a function');
        throw new Error('onUpdate must be a function');
    };
    var easingFunctions = {
        linear:function(t){return t;},
        easeIn:function(t){return t * t;},
        easeOut:function(t){return t * (2 - t);},
        easeInOut:function(t){return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;}
    };
    var easingFunc = easingFunctions[easing] || easingFunctions.linear;
    var distance = to - from;
    var startTime = null;
    var animationId = null;
    var lastValue = null;
    var formatNumber = function(value){
        var factor = Math.pow(10,decimals);
        return Math.round(value * factor) / factor;
    };
    var step = function(){
        var currentTime = new Date().getTime();
        if(!startTime) startTime = currentTime;
        var elapsed = currentTime - startTime;
        var progress = Math.min(elapsed / duration,1);
        progress = easingFunc(progress);
        var currentValue = from + distance * progress;
        var formattedValue = formatNumber(currentValue);
        if(formattedValue !== lastValue){
            lastValue = formattedValue;
            onUpdate(formattedValue);
        };
        if(progress < 1){
            animationId = setTimeout(step,16);
        } else if (typeof onComplete === 'function'){
            onComplete();
        }
    };
    step();
    return {
        stop:function(){
            if(animationId){
                clearTimeout(animationId);
                animationId = null;
            }
        }
    }
};

/**
 * 右键菜单管理器 (单例模式)
 * 
 * 这是一个全局右键菜单解决方案，支持多区域注册、默认菜单、动画效果等功能。
 * 确保同一时间页面上只显示一个右键菜单。
 * 
 * @function rightClick
 * @param {Object} options - 配置选项
 * @param {Array} options.menuItems - 菜单项数组
 * @param {string} [options.menuClass] - 菜单容器CSS类名(以防被覆盖，请尽量约束样式或使用“!important”)
 * @param {string} [options.itemClass] - 菜单项CSS类名(以防被覆盖，请尽量约束样式或使用“!important”)
 * @param {string} [options.activeClass] - 激活状态CSS类名(以防被覆盖，请尽量约束样式或使用“!important”)
 * @param {boolean} [options.preventDefault=true] - 是否阻止默认右键行为
 * @param {number} [options.animationDuration=200] - 动画持续时间(ms)
 * @param {boolean} [options.closeOnClickOutside=true] - 点击外部是否关闭菜单
 * @param {boolean} [options.closeOnScroll=true] - 滚动时是否关闭菜单
 * @param {string|HTMLElement} [options.triggerArea=document] - 触发区域选择器或DOM元素
 * @param {boolean} [options.isDefault=false] - 是否设为默认菜单(未匹配区域时触发)
 * 
 * @returns {Object} 菜单API对象
 * 
 * @example
 * // 基本使用
 * const menu = rightClick({
 *   triggerArea: '#app', // 指定触发区域
 *   menuItems: [
 *     { text: '复制', action: () => console.log('复制') },
 *     { text: '粘贴', action: () => console.log('粘贴') }
 *   ]
 * });
 * 
 * @example
 * // 默认菜单(整个页面未匹配区域时触发)
 * const defaultMenu = rightClick({
 *   isDefault: true,
 *   menuItems: [
 *     { text: '全局选项1', action: () => alert('选项1') },
 *     { text: '全局选项2', action: () => alert('选项2') }
 *   ]
 * });
 * 
 * @example
 * // 带图标的菜单项
 * rightClick({
 *   menuItems: [
 *     { 
 *       text: '下载', 
 *       icon: '↓', 
 *       action: downloadFile 
 *     },
 *     { 
 *       text: '删除', 
 *       icon: '×', 
 *       action: deleteItem,
 *       disabled: true // 禁用状态
 *     }
 *   ]
 * });
 */
const rightClick = (function(){
    let currentMenu = null;
    const registeredMenus = [];
    const styleId = random(16,'str');
    let showTime = 0;
    
    // 显示菜单的统一方法
    function showMenu(menu,x,y){
        // 如果已经有其他菜单显示，先隐藏
        if(currentMenu && currentMenu !== menu){
            currentMenu.hide();
        };
        // 显示新菜单
        currentMenu = menu;
        menu.show(x,y);
    };
    
    // 全局事件处理函数
    function handleGlobalContextMenu(e){
        // 检查是否在已注册的区域内
        for(const menuInfo of registeredMenus){
            if(menuInfo.triggerArea.contains(e.target)){
                e.preventDefault();
                if (currentMenu && currentMenu === menuInfo.menu) {
                    currentMenu.hide();
                    currentMenu = null;
                };
                setTimeout(function(){
                    showMenu(menuInfo.menu, e.clientX, e.clientY);
                },showTime);
                return;
            }
        };
        // 默认菜单处理
        for(const menuInfo of registeredMenus){
            if(menuInfo.isDefault){
                e.preventDefault();
                if (currentMenu && currentMenu === menuInfo.menu) {
                    currentMenu.hide();
                    currentMenu = null;
                };
                setTimeout(function(){
                    showMenu(menuInfo.menu, e.clientX, e.clientY);
                },showTime);
                return;
            }
        }
    };
    
    // 全局点击外部处理
    function handleGlobalClickOutside(e){
        if (currentMenu && !currentMenu.element.contains(e.target)) {
            currentMenu.hide();
            currentMenu = null;
        }
    };
    
    // 全局滚动处理
    function handleGlobalScroll(){
        if (currentMenu) {
            currentMenu.hide();
            currentMenu = null;
        }
    };
    
    // 初始化全局监听
    document.addEventListener('contextmenu', handleGlobalContextMenu);
    document.addEventListener('click', handleGlobalClickOutside);
    window.addEventListener('scroll', handleGlobalScroll, true);
    
    createStyle();
    
    function createStyle(){
        const styles = createTag('style',[['id',styleId],['rel','stylesheet']]);
        const style = `
            .menu-${styleId} {
                position: fixed;
                display: none;
                opacity: 0;
                transform: scale(0.95);
                box-shadow: 0 0 8px rgba(191,191,191,0.8);
                background-color: #ffffff;
                border-radius: 4px;
                font-size: 16px;
                padding: 3px 0;
            }
            .menuItem-${styleId} {
                padding: 2px 5px;
            }
            .menuItem-${styleId} .menu-item-text{
                padding: 4px 5px;
                background-color: #ffffff;
                color: #333333;
                border-radius: 4px;
                cursor: pointer;
                transition: background-color 0.3s ease,color 0.3s ease;
                text-align: left;
            }
            .menuItem-${styleId}.select-${styleId} .menu-item-text{
                background-color: #246bcc;
                color: #ffffff;
            }
            .menuItem-${styleId}.separator{
                border-bottom: 1px solid #cecece;
                margin-bottom: 3px;
            }
            .menuItem-${styleId}.disabled .menu-item-text,.menuItem-${styleId}.select-${styleId}.disabled .menu-item-text{
                transition: none;
                cursor: default;
                background-color: #edecec;
                opacity: 0.6;
            }
        `;
        styles.innerHTML = style;
        document.head.appendChild(styles);
    };
    
    return function(options){
        // 默认配置
        const defaults = {
            menuItems: [],
            menuClass: `menu-${styleId}`,
            itemClass: `menuItem-${styleId}`,
            activeClass: `select-${styleId}`,
            preventDefault: true,
            animationDuration: 200,
            closeOnClickOutside: true,
            closeOnScroll: true,
            triggerArea: document,
            isDefault: false
        };
        
        // 合并配置
        const config = {
            ...defaults,
            ...options,
            menuClass: `${defaults.menuClass}${options.menuClass ? ' ' + options.menuClass : ''}`,
            itemClass: `${defaults.itemClass}${options.itemClass ? ' ' + options.itemClass : ''}`,
            activeClass: `${defaults.activeClass}${options.activeClass ? ' ' + options.activeClass : ''}`
        };
        
        // 获取触发区域
        const triggerArea = typeof config.triggerArea === 'string' ? document.querySelector(config.triggerArea) : config.triggerArea;
        
        // 创建菜单容器
        const menuElement = createTag('div',[['class',config.menuClass]]);
        Object.assign(menuElement.style,{
            zIndex: getMaxZIndex(),
            transition: `opacity ${config.animationDuration}ms ease, transform ${config.animationDuration}ms ease`
        });
        
        // 创建菜单项
        function createMenuItems(items){
            menuElement.innerHTML = '';
            items.forEach(item => {
                const menuItem = createTag('div',[['class',config.itemClass]]);
                if(item.icon){
                    const icon = createTag('span',[['class',"menu-item-icon"]],item.icon);
                    menuItem.appendChild(icon);
                };
                const text = createTag('div',[['class',"menu-item-text"]],item.text);
                menuItem.appendChild(text);
                if(item.separator){
                    menuItem.classList.add('separator');
                };
                if(item.disabled){
                    menuItem.classList.add("disabled");
                }else{
                    menuItem.addEventListener('click',function(e){
                        item.action?.();
                        hide();
                        e.stopPropagation();
                    });
                    menuItem.addEventListener('mouseenter',function(){
                        const classesToAdd = config.activeClass.split(/\s+/);
                        menuItem.classList.add(...classesToAdd);
                    });
                    menuItem.addEventListener('mouseleave',function(){
                        const classesToAdd = config.activeClass.split(/\s+/);
                        menuItem.classList.remove(...classesToAdd);
                    })
                };
                menuElement.appendChild(menuItem);
            });
        };
        
        // 初始化菜单项
        createMenuItems(config.menuItems);
        document.body.appendChild(menuElement);
        
        // 计算最佳显示位置
        function calculatePosition(x,y){
            // 临时显示菜单以获取尺寸
            const originalDisplay = menuElement.style.display;
            const originalOpacity = menuElement.style.opacity;
            const originalTransform = menuElement.style.transform;
            
            menuElement.style.display = 'block';
            menuElement.style.opacity = '0';
            menuElement.style.transform = 'scale(1)';
            menuElement.style.visibility = 'hidden'; // 防止闪烁
            menuElement.style.left = '0';
            menuElement.style.top = '0';
            
            const menuRect = menuElement.getBoundingClientRect();
            const menuWidth = menuRect.width;
            const menuHeight = menuRect.height;
            
            // 恢复原始状态
            menuElement.style.display = originalDisplay;
            menuElement.style.opacity = originalOpacity;
            menuElement.style.transform = originalTransform;
            menuElement.style.visibility = '';
            
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
            
            let finalX = x + 5;
            let finalY = y + 5;
            let transformOrigin = 'top left';
            
            if (x + menuWidth > windowWidth) {
                finalX = x - menuWidth - 5;
                transformOrigin = 'top right';
            }
            if (y + menuHeight > windowHeight) {
                finalY = y - menuHeight - 5;
                transformOrigin = transformOrigin.replace('top', 'bottom');
            }
            
            finalX = Math.max(5, Math.min(finalX, windowWidth - menuWidth - 5));
            finalY = Math.max(5, Math.min(finalY, windowHeight - menuHeight - 5));
            
            return {
                x: finalX,
                y: finalY,
                transformOrigin,
                width: menuWidth,
                height: menuHeight
            };
        };
        
        // 隐藏菜单
        function hide() {
            if (menuElement.style.display === 'none') return;

            menuElement.style.opacity = '0';
            menuElement.style.transform = 'scale(0.95)';

            setTimeout(() => {
                menuElement.style.display = 'none';
            }, config.animationDuration);
        };
        
        // 显示菜单
        function show(x, y) {
            const position = calculatePosition(x, y);
            Object.assign(menuElement.style, {
                display: 'block',
                left: `${position.x}px`,
                top: `${position.y}px`,
                transformOrigin: position.transformOrigin
            });
            
            // 触发重绘
            void menuElement.offsetHeight;
            
            // 动画效果
            menuElement.style.opacity = '1';
            menuElement.style.transform = 'scale(1)';
            showTime = config.animationDuration;
        };
        
        // 创建菜单API对象
        const menuApi = {
            element: menuElement,
            show,
            hide,
            updateItems: function (newItems) {
                createMenuItems(newItems);
            },
            destroy: function () {
                if (currentMenu?.element === menuElement) {
                    currentMenu = null;
                }
                document.body.removeChild(menuElement);
                const index = registeredMenus.findIndex(m => m.menu === menuApi);
                if (index !== -1) {
                    registeredMenus.splice(index, 1);
                }
            }
        };
        
        // 注册当前菜单
        registeredMenus.push({
            menu: menuApi,
            triggerArea,
            isDefault: config.isDefault
        });

        return menuApi;
    }
})();

/**
 * 使指定元素及其直接子元素可拖拽，实现拖拽排序功能
 * @param { string } [element='body'] 目标元素，该元素下的直接子元素将被设置为可拖拽
 * @example
 * // 直接让body下直接一级元素可拖拽
 * draggable()/draggable('body');
 * // 指定元素下直接一级子元素可拖拽
 * draggable("#div")
 */
function draggable(element="body") {
    var node=document.querySelector(element);
    if(!node) return;
    function _getDirectChildren(container) {
        var objChind = [];
        var objs = container.getElementsByTagName("*");
        for(var i = 0, j = objs.length; i < j; ++i) {
            if(objs[i].nodeType != 1) continue;
            var temp = objs[i].parentNode;
            if(temp.nodeType == 1) {
                if(temp == container) {
                    objChind[objChind.length] = objs[i];
                }
            } else if(temp.parentNode == container) {
                objChind[objChind.length] = objs[i];
            }
        }
        return objChind;
    }
    function _index(el) {
        var index = 0;
        if(!el || !el.parentNode) return -1;
        while (el && (el = el.previousElementSibling)) {
            index++;
        }
        return index;
    }
    function _animate(prevRect, target) {
        var ms = 300;
        if(ms) {
            var currentRect = target.getBoundingClientRect();
            if(prevRect.nodeType === 1) {
                prevRect = prevRect.getBoundingClientRect();
            }
            _css(target, 'transition', 'none');
            _css(target, 'transform', 'translate3d(' + (prevRect.left - currentRect.left) + 'px,' + (prevRect.top - currentRect.top) + 'px,0)');
            target.offsetWidth; // 触发重绘
            _css(target, 'transition', 'all ' + ms + 'ms');
            _css(target, 'transform', 'translate3d(0,0,0)');
            clearTimeout(target.animated);
            target.animated = setTimeout(function() {
                _css(target, 'transition', '');
                _css(target, 'transform', '');
                target.animated = false;
            }, ms);
        }
    }
    function _css(el, prop, val) {
        el.style[prop] = val + (typeof val === 'string' ? '' : 'px');
    }
    // 主逻辑开始
    var objChind = _getDirectChildren(node);
    for(var i = 0; i < objChind.length; i++) {
        if(objChind[i].getAttribute("draggable") != "true") {
            objChind[i].setAttribute("draggable", "true");	
        }
    }
    var draging = null;
    node.ondragstart = function(event) {
        if(event.target.getAttribute("draggable") != "true") return;
        event.dataTransfer.setData("text", event.target.innerText);
        draging = event.target;
    };
    node.ondragover = function(event) {
        event.preventDefault();
        if(!draging) return;
        var target = event.target;
        // 向上查找可拖拽的父元素
        while(target && target !== node && target.getAttribute("draggable") != "true") {
            target = target.parentNode;
        }
        if(!target || target.getAttribute("draggable") != "true" || target === draging) {
            return;
        }
        if(target.animated) return;
        var targetRect = target.getBoundingClientRect();
        var dragingRect = draging.getBoundingClientRect();
        if(_index(draging) < _index(target)) {
            target.parentNode.insertBefore(draging, target.nextSibling);
        } else {
            target.parentNode.insertBefore(draging, target);
        }
        _animate(dragingRect, draging);
        _animate(targetRect, target);
    };
    
    // 添加拖拽结束事件清理
    node.ondragend = function(event) {
        draging = null;
    };
};

/**
 * 全屏滚动切页组件 - 流畅优化版
 * @param {string|HTMLElement} container - 容器选择器或DOM节点
 * @param {Object} [options] - 配置项
 * @param {number} [options.duration=800] - 动画时长(ms)
 * @param {string} [options.easing='cubic-bezier(0.25, 0.1, 0.25, 1)'] - 动画缓动函数
 * @param {string} [options.direction='vertical'] - 'vertical'垂直|'horizontal'水平
 * @param {boolean} [options.infinite=true] - 是否无限循环
 * @param {Function} [options.beforeChange] - 切换前回调(prevIndex,nextIndex)
 * @param {Function} [options.afterChange] - 切换后回调(currentIndex)
 * @param {number} [options.throttleTime=800] - 滚轮节流时间(ms)
 * @param {number} [options.sensitivity=1] - 滚轮灵敏度(0-1)
 * 
 * @example // 基础使用
 * const pager = scrollPager('#pages', {
 *   duration: 500,
 *   afterChange: (index) => {
 *     console.log('当前页:', index + 1)
 *   }
 * });
 * 
 * @example // 手动控制
 * btnNext.addEventListener('click', () => pager.next());
 */
function scrollPager(container, options = {}) {
  // 合并默认配置
  const config = {
    duration: 800,
    easing: 'cubic-bezier(0.25, 0.1, 0.25, 1)',
    direction: 'vertical',
    infinite: true,
    throttleTime: 800,
    sensitivity: 1,
    ...options
  };

  // 获取容器元素
  const containerEl = typeof container === 'string' 
    ? document.querySelector(container) 
    : container;
  
  if (!containerEl) {
    console.error('ScrollPager: Container not found');
    return;
  }

  // 设置容器样式
  Object.assign(containerEl.style, {
    overflow: 'hidden',
    position: 'relative',
    height: '100vh',
    width: '100%',
    touchAction: 'none' // 防止触摸默认行为
  });

  // 获取所有原始页面
  const originalPages = Array.from(containerEl.children);
  if (originalPages.length === 0) return;

  // 克隆首尾页面用于无限滚动
  let pages = [...originalPages];
  if (config.infinite && originalPages.length > 1) {
    const firstClone = originalPages[0].cloneNode(true);
    const lastClone = originalPages[originalPages.length - 1].cloneNode(true);
    
    containerEl.insertBefore(lastClone, originalPages[0]);
    containerEl.appendChild(firstClone);
    
    pages = [lastClone, ...originalPages, firstClone];
  }

  // 设置页面样式
  pages.forEach(page => {
    Object.assign(page.style, {
      position: 'absolute',
      top: '0',
      left: '0',
      width: '100%',
      height: '100%',
      willChange: 'transform', // 提示浏览器优化
      backfaceVisibility: 'hidden' // 防止闪烁
    });
  });

  // 当前页面索引（考虑克隆页）
  let currentIndex = config.infinite ? 1 : 0;
  let isAnimating = false;
  let animationFrameId = null;
  let startTimestamp = null;
  let startPosition = 0;
  let targetPosition = 0;

  // 初始化页面位置
  function initPages() {
    cancelAnimationFrame(animationFrameId);
    pages.forEach((page, index) => {
      const translateValue = (index - currentIndex) * 100;
      page.style.transition = 'none';
      page.style.transform = config.direction === 'vertical' 
        ? `translateY(${translateValue}%)` 
        : `translateX(${translateValue}%)`;
    });
  }

  // 滚动到指定页面
  function scrollTo(index, isInstant = false) {
    if (isAnimating) return;
    
    const prevIndex = currentIndex;
    currentIndex = Math.max(0, Math.min(index, pages.length - 1));
    isAnimating = true;

    // 执行切换前回调（使用原始页面索引）
    const beforeChangePromise = typeof config.beforeChange === 'function'
      ? config.beforeChange(
          getOriginalIndex(prevIndex),
          getOriginalIndex(currentIndex))
      : Promise.resolve();

    beforeChangePromise.then(() => {
      // 检查是否需要无缝跳转
      let needsReset = false;
      let resetIndex = currentIndex;
      
      if (config.infinite && pages.length > 1) {
        if (currentIndex >= pages.length - 1) {
          needsReset = true;
          resetIndex = 1;
        } else if (currentIndex <= 0) {
          needsReset = true;
          resetIndex = pages.length - 2;
        }
      }

      // 如果需要无缝跳转
      if (needsReset) {
        animateScroll(isInstant).then(() => {
          isAnimating = false;
          currentIndex = resetIndex;
          updatePagesPosition(true);
          triggerAfterChange();
        });
      } else {
        animateScroll(isInstant).then(() => {
          isAnimating = false;
          triggerAfterChange();
        });
      }
    });
  }

  // 平滑滚动动画
  function animateScroll(isInstant) {
    return new Promise(resolve => {
      if (isInstant) {
        updatePagesPosition(true);
        resolve();
        return;
      }

      startTimestamp = null;
      startPosition = currentIndex;
      targetPosition = currentIndex;

      const animate = (timestamp) => {
        if (!startTimestamp) startTimestamp = timestamp;
        const progress = Math.min((timestamp - startTimestamp) / config.duration, 1);
        
        updatePagesPosition(false, progress);
        
        if (progress < 1) {
          animationFrameId = requestAnimationFrame(animate);
        } else {
          resolve();
        }
      };

      animationFrameId = requestAnimationFrame(animate);
    });
  }

  // 获取原始页面索引（不考虑克隆页）
  function getOriginalIndex(index) {
    if (!config.infinite) return index;
    
    if (index <= 0) return originalPages.length - 1;
    if (index >= pages.length - 1) return 0;
    return index - 1;
  }

  // 更新页面位置
  function updatePagesPosition(isInstant, progress = 1) {
    const transition = isInstant 
      ? 'none' 
      : `transform ${config.duration}ms ${config.easing}`;
    
    pages.forEach((page, i) => {
      page.style.transition = transition;
      
      let translateValue;
      if (isInstant || progress === 1) {
        translateValue = (i - currentIndex) * 100;
      } else {
        const startValue = (i - startPosition) * 100;
        const endValue = (i - targetPosition) * 100;
        translateValue = startValue + (endValue - startValue) * progress;
      }

      page.style.transform = config.direction === 'vertical'
        ? `translateY(${translateValue}%)`
        : `translateX(${translateValue}%)`;
    });
  }

  // 触发切换后回调
  function triggerAfterChange() {
    if (typeof config.afterChange === 'function') {
      config.afterChange(getOriginalIndex(currentIndex));
    }
  }

  // 处理滚轮事件
  function handleWheel(e) {
    if (isAnimating) {
      e.preventDefault();
      return;
    }

    const delta = config.direction === 'vertical' 
      ? e.deltaY * config.sensitivity
      : e.deltaX * config.sensitivity;
    
    const direction = delta > 0 ? 1 : -1;
    
    // 非无限模式边界检查
    if (!config.infinite) {
      if ((direction < 0 && currentIndex === 0) || 
          (direction > 0 && currentIndex === originalPages.length - 1)) {
        e.preventDefault();
        return;
      }
    }
    
    scrollTo(currentIndex + direction);
    e.preventDefault();
  }

  // 处理触摸事件
  function handleTouchStart(e) {
    if (isAnimating) return;
    
    const touch = e.touches[0];
    startTouch = {
      x: touch.clientX,
      y: touch.clientY,
      time: Date.now()
    };
  }

  function handleTouchMove(e) {
    if (!startTouch || isAnimating) return;
    
    const touch = e.touches[0];
    const deltaX = touch.clientX - startTouch.x;
    const deltaY = touch.clientY - startTouch.y;
    
    // 根据滚动方向判断是否处理
    if (config.direction === 'vertical' && Math.abs(deltaY) > Math.abs(deltaX)) {
      e.preventDefault();
    } else if (config.direction === 'horizontal' && Math.abs(deltaX) > Math.abs(deltaY)) {
      e.preventDefault();
    }
  }

  function handleTouchEnd(e) {
    if (!startTouch || isAnimating) return;
    
    const touch = e.changedTouches[0];
    const deltaTime = Date.now() - startTouch.time;
    const deltaX = touch.clientX - startTouch.x;
    const deltaY = touch.clientY - startTouch.y;
    
    let direction = 0;
    if (config.direction === 'vertical') {
      const distance = deltaY;
      const isQuickSwipe = deltaTime < 300 && Math.abs(distance) > 50;
      if (isQuickSwipe || Math.abs(distance) > window.innerHeight / 3) {
        direction = distance > 0 ? 1 : -1;
      }
    } else {
      const distance = deltaX;
      const isQuickSwipe = deltaTime < 300 && Math.abs(distance) > 50;
      if (isQuickSwipe || Math.abs(distance) > window.innerWidth / 3) {
        direction = distance > 0 ? 1 : -1;
      }
    }
    
    if (direction !== 0) {
      scrollTo(currentIndex + direction);
    }
    
    startTouch = null;
  }

  // 初始化
  initPages();

  // 事件监听
  const throttledWheel = throttle(handleWheel, config.throttleTime,true);
  containerEl.addEventListener('wheel', (e) => {
    // 非无限模式 + 到达边界时，直接拦截！
    if (!config.infinite) {
        const delta = config.direction === 'vertical' ? e.deltaY : e.deltaX;
        const direction = delta > 0 ? 1 : -1;

        if ((direction < 0 && currentIndex === 0) ||  // 第一页还往上滑
            (direction > 0 && currentIndex === originalPages.length - 1)) {  // 最后一页还往下滑
            e.preventDefault();
            return; // 直接退出，不进入节流函数！
        }
    }
    // 只有真正需要滚动时，才触发节流
    throttledWheel(e);
    }, { passive: false });
  
  // 触摸事件支持
  let startTouch = null;
  containerEl.addEventListener('touchstart', handleTouchStart, { passive: true });
  containerEl.addEventListener('touchmove', handleTouchMove, { passive: false });
  containerEl.addEventListener('touchend', handleTouchEnd, { passive: true });

  // 返回API方法
  return {
    next: () => {
      const nextIndex = config.infinite 
        ? currentIndex + 1
        : Math.min(currentIndex + 1, originalPages.length - 1);
      scrollTo(nextIndex);
    },
    prev: () => {
      const prevIndex = config.infinite
        ? currentIndex - 1
        : Math.max(currentIndex - 1, 0);
      scrollTo(prevIndex);
    },
    scrollTo: (index) => scrollTo(config.infinite ? index + 1 : index),
    getCurrentIndex: () => getOriginalIndex(currentIndex),
    getTotalPages: () => originalPages.length,
    destroy: () => {
      cancelAnimationFrame(animationFrameId);
      containerEl.removeEventListener('wheel', throttledWheel);
      containerEl.removeEventListener('touchstart', handleTouchStart);
      containerEl.removeEventListener('touchmove', handleTouchMove);
      containerEl.removeEventListener('touchend', handleTouchEnd);
      
      // 恢复原始DOM结构
      if (config.infinite && pages.length > originalPages.length) {
        containerEl.removeChild(pages[pages.length - 1]);
        containerEl.removeChild(pages[0]);
      }
    }
  };
}

/**
 * 计算指定日期到今天的时间差
 * @param {Date|string} targetDate 目标日期（支持 Date 对象或字符串格式：2023.10.01 / 2023/10/01 / 2023-10-01）
 * @param {string} [unit] 可选单位（'day' | 'hour' | 'minute' | 'second' | 'ms'）
 * @returns {number|Object} 传 unit 返回数字，不传返回 {day, hour, minute, second, ms}
 */
function getDateDiff(targetDate, unit) {
    // 1. 统一处理输入日期（兼容字符串和 Date 对象）
    let date;
    if (targetDate instanceof Date) {
        date = new Date(targetDate);
    } else {
        // 替换非标准分隔符为横杠（如 2023.10.01 → 2023-10-01）
        const normalizedDateStr = String(targetDate).replace(/[./]/g, '-');
        date = new Date(normalizedDateStr);
    }
    if (isNaN(date.getTime())) throw new Error(`Invalid date: ${targetDate}`);

    // 2. 计算时间差（毫秒）
    const now = new Date();
    const diffMs = Math.floor(now - date);

    // 3. 如果传了 unit，返回对应单位的数字
    if (unit) {
        switch (unit.toLowerCase()) {
            case 'ms': return diffMs;
            case 'second': return Math.floor(diffMs / 1000);
            case 'minute': return Math.floor(diffMs / (1000 * 60));
            case 'hour': return Math.floor(diffMs / (1000 * 60 * 60));
            case 'day': return Math.floor(diffMs / (1000 * 60 * 60 * 24));
            default: throw new Error('Invalid unit. Use: day/hour/minute/second/ms');
        }
    }

    // 4. 不传 unit 时返回对象
    const seconds = Math.floor(diffMs / 1000);
    const minutes = Math.floor(seconds / 60);
    const hours = Math.floor(minutes / 60);
    const days = Math.floor(hours / 24);

    return {
        day: days,
        hour: hours % 24,
        minute: minutes % 60,
        second: seconds % 60,
        ms: diffMs % 1000
    };
};

/**
 * 图片查看器组件 - 弹窗式图片浏览工具
 * @param {string|Array<string|HTMLElement>|HTMLElement} input - 图片源，支持字符串路径、DOM元素、图片数组
 * @param {Object} [obj] - 配置选项
 * @param {number} [obj.currIndex=0] - 初始显示第几张图片的索引（从0开始），默认 0
 * @param {boolean} [obj.loop=false] - 是否允许循环切换（最后一张后接第一张，第一张前为最后一张），默认 false
 * @param {number} [obj.max=2] - 图片最大放大倍数，默认 2 倍
 * @param {number} [obj.min=0.3] - 图片最小缩小倍数，默认 0.3 倍
 * @param {number} [obj.curr=0.2] - 每次点击放大/缩小按钮时变化的倍率步长，默认 0.2 倍
 * @param {boolean} [obj.showPage=false] - 是否显示分页，默认 false
 * @param {boolean} [obj.drag=true] - 是否支持拖拽，默认 true
 * 
 * 功能特性：
 * - 以模态弹窗形式展示图片，支持放大、缩小、旋转、左右切换
 * - 支持背景模糊遮罩与半透明黑色背景，提升视觉层次
 * - 提供图片操作按钮：放大/缩小/左旋/右旋/重置/关闭/上一张/下一张
 * - 支持键盘和鼠标交互，响应迅速，交互友好
 * - 每个图片查看器实例拥有独立样式作用域，避免样式污染
 * - 自动清理 DOM，防止内存泄漏
 * - 支持传入图片 URL 字符串、DOM 中的 <img> 元素、或包含图片的容器元素
 * 
 * @example // 基础用法：传入单张图片路径
 * imageViewer('path/to/image.jpg');
 * 
 * @example // 传入图片数组
 * imageViewer(['1.jpg', '2.jpg', '3.jpg'], {
 *   currIndex: 1,  // 从第二张开始显示
 *   loop: true     // 允许循环切换
 * });
 * 
 * @example // 从 DOM 中的图片元素或容器中提取图片
 * imageViewer(document.querySelector('.image-gallery'), {
 *   currIndex: 0,
 *   max: 3         // 最大放大到3倍
 * });
 */
function imageViewer(input, obj = {}) {
    // 存储图片元素地址
    const imgs = [];
    const config = {
        currIndex: obj.currIndex ?? 0, // 当前是第几张图片
        loop: obj.loop ?? false, // 是否可以无限切换
        max: obj.max ?? 2, // 最大放大倍率
        min: obj.min ?? 0.3, // 最小缩小倍率
        curr: obj.curr ?? 0.2, // 变化尺寸
        showPage: obj.showPage ?? false, // 显示分页
        drag: obj.drag ?? true // 是否可以拖拽图片
    };
    let currScale = 1; // 当前缩放比例
    let currRotation = 0; // 当前旋转角度
    let flipX = 1; // X轴翻转状态：1正常，-1翻转
    let flipY = 1; // Y轴翻转状态：1正常，-1翻转
    
    const styleId = random("16", "str");
    if (typeof input === "string") { // 传入单个图片路径字符串，如 "a.png"
        imgs.push(input);
    } else if (Array.isArray(input)) { // 传入一个 数组
        input.forEach(item => {
            if (typeof item === "string") {
                if (!imgs.includes(item)) imgs.push(item);
            } else if (item instanceof HTMLElement) {
                const imgElements = item.querySelectorAll('img');
                imgElements.forEach(imgEl => {
                    const src = imgEl.getAttribute("src");
                    if (src && !imgs.includes(src)) imgs.push(src);
                });
            }
        });
    } else if (input instanceof HTMLElement) { // 传入一个 DOM 元素，从中查找 <img> 并提取 src
        const imgElements = input.querySelectorAll("img");
        imgElements.forEach(imgEl => {
            const src = imgEl.getAttribute("src");
            if (src) imgs.push(src);
        });
    };
    if (imgs.length === 0) return;
    
    const styles = () => {
        let style = createTag("style", [["id", styleId], ["rel", "stylesheet"]]);
        var htmlStyle = "";
        htmlStyle += `#dialog_${styleId}{width: 100%;height: 100%;background-color: transparent;padding: 0;margin: 0;outline: none;border: none;min-width: 100%;min-height: 100%;}`;
        htmlStyle += `#dialog_${styleId}::backdrop{background-color: rgba(0,0,0,0.5);backdrop-filter: blur(5px);}`;
        htmlStyle += `.image-view-box-${styleId}{width: 100%;height: 100%;position: relative;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}`;
        htmlStyle += `.image-view-operate-${styleId}{width: fit-content;height: 44px;background-color: rgba(0,0,0,0.5);border-radius: 22px;position: absolute;bottom: 24px;left: 50%;transform: translateX(-50%);display: grid;grid-template-columns: repeat(7, 1fr);grid-template-rows: 1fr;align-items: center;z-index: 9;}`;
        htmlStyle += `.image-view-close-${styleId}{position: absolute;top: 24px;right: 24px;cursor: pointer;z-index: 9;}`;
        htmlStyle += `.image-view-left-${styleId}{position: absolute;top: 50%;left: 24px;cursor: pointer;z-index: 9;transform: translateY(-50%);}`;
        htmlStyle += `.image-view-right-${styleId}{position: absolute;top: 50%;right: 24px;cursor: pointer;z-index: 9;transform: translateY(-50%);}`;
        htmlStyle += `.image-view-image-${styleId} img{width: auto;height: auto;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%) scale(1) rotate(0deg);transform-style: preserve-3d;max-width: 100%;max-height: 100%;transition: all 0.3s ease;transition-delay: 0s;cursor: grab;}`;
        htmlStyle += `.image-view-image-${styleId}{position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 8;overflow: hidden;perspective: 1000px;}`;
        htmlStyle += `.image-view-svg-max-${styleId}{width: 50px;height: 50px;}`;
        htmlStyle += `.image-view-item-${styleId}{display: flex;justify-content: center;padding: 0 16px;}`;
        htmlStyle += `.image-view-icon-${styleId}{cursor: pointer;width: 24px;height: 24px;}`;
        htmlStyle += `.image-view-svg-max-close-${styleId}{width: 42px;height: 42px;}`;
        htmlStyle += `.image-view-number-${styleId}{position: absolute;bottom: 80px;left: 50%;transform: translateX(-50%);z-index: 9;color: #ffffff;font-size: 20px;font-weight: bold;}`;
        style.innerHTML = htmlStyle;
        document.head.appendChild(style);
    };
    
    let dialog = createTag("dialog", [["id", "dialog_" + styleId]]);
    let imageViewBox = createTag("div", [["class", "image-view-box-" + styleId]]);
    
    // 图片区域
    let imageViewImage = createTag("div", [["class", "image-view-image-" + styleId]]);
    let img = new Image();
    img.src = imgs[config.currIndex];
    img.alt = "暂无图片";
    
    // 添加拖拽相关变量
    let isDragging = false;
    let startX, startY;
    let offsetX = 0, offsetY = 0;

    // 鼠标/触摸事件监听
    if(config.drag) {
        img.addEventListener('mousedown', startDrag);
        img.addEventListener('mousemove', drag);
        img.addEventListener('mouseup', endDrag);
        img.addEventListener('mouseleave', endDrag);
        img.addEventListener('touchstart', startDrag, { passive: false });
        img.addEventListener('touchmove', drag, { passive: false });
        img.addEventListener('touchend', endDrag);
    };

    function startDrag(e) {
        e.preventDefault();
        isDragging = true;
        
        const clientX = e.clientX || e.touches[0].clientX;
        const clientY = e.clientY || e.touches[0].clientY;
        startX = clientX - offsetX;
        startY = clientY - offsetY;
        
        img.style.cursor = 'grabbing';
        img.style.transition = 'none';
    };

    function drag(e) {
        if (!isDragging) return;
        e.preventDefault();
        const clientX = e.clientX || e.touches[0].clientX;
        const clientY = e.clientY || e.touches[0].clientY;
        
        offsetX = clientX - startX;
        offsetY = clientY - startY;
        updateImageTransform();
    };

    function endDrag() {
        if (!isDragging) return;
        isDragging = false;
        img.style.cursor = currScale > 1 ? 'grab' : 'default';
        img.style.transition = 'transform 0.3s ease';
    };

    // 更新图片变换
    function updateImageTransform() {
        const transform = `translate(calc(-50% + ${offsetX}px), calc(-50% + ${offsetY}px)) scale(${currScale}) rotate(${currRotation}deg) scaleX(${flipX}) scaleY(${flipY})`;
        img.style.transform = transform;
    };

    function resetPosition() {
        offsetX = 0;
        offsetY = 0;
        updateImageTransform();
    };

    imageViewImage.appendChild(img);
    imageViewBox.appendChild(imageViewImage);

    // 数字区域
    let divNum = createTag("div",[["class",`image-view-number-${styleId}`]]);
    let spanCurr = createTag("span", null, config.currIndex + 1);
    let spanSpan = createTag("span", null, "/");
    let spanTotal = createTag("span", null, imgs.length);
    divNum.appendChild(spanCurr);
    divNum.appendChild(spanSpan);
    divNum.appendChild(spanTotal);
    if(config.showPage) {
        imageViewBox.appendChild(divNum);
    }; 

    // 操作区域
    let imageViewOperate = createTag("div", [["class", "image-view-operate-" + styleId]]);
    
    // 上下翻转
    let imageViewItemSXFZ = createTag("div", [["class", "image-view-item-" + styleId], ["title", "上下翻转"]]);
    let sxfzSvg = createSvg("M608 128c12.256 0 22.08 8.8 29.248 16.576 1.824 1.76 64.384 64.128 187.648 187.072a32 32 0 0 1-45.248 45.248L640 237.248V864a32 32 0 0 1-64 0V160a32 32 0 0 1 32-32z m-189.728 0a32 32 0 0 1 32 32v704a32 32 0 0 1-32 32c-10.72 0-19.584-6.72-26.432-13.632l-190.464-190.016a32 32 0 0 1 45.248-45.248l139.648 139.648V160a32 32 0 0 1 32-32z", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemSXFZ.appendChild(sxfzSvg);
    imageViewOperate.appendChild(imageViewItemSXFZ);

    // 左右翻转
    let imageViewItemZYFZ = createTag("div", [["class", "image-view-item-" + styleId], ["title", "左右翻转"]]);
    let zyfzSvg = createSvg("M897.152 606.848c0 12.288-8.8 22.08-16.576 29.28-1.76 1.824-64.128 64.384-187.072 187.648a32 32 0 0 1-45.28-45.28l139.68-139.648H161.152a32 32 0 0 1 0-64h704a32 32 0 0 1 32 32z m0-189.696a32 32 0 0 1-32 32h-704a32 32 0 0 1-32-32c0-10.752 6.72-19.584 13.6-26.464L332.8 200.224a32 32 0 0 1 45.28 45.28L238.4 385.152h626.752a32 32 0 0 1 32 32z", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemZYFZ.appendChild(zyfzSvg);
    imageViewOperate.appendChild(imageViewItemZYFZ);

    // 缩小
    let imageViewItemSX = createTag("div", [["class", "image-view-item-" + styleId], ["title", "缩小"]]);
    let sxSvg = createSvg("m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704M352 448h256a32 32 0 0 1 0 64H352a32 32 0 0 1 0-64", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemSX.appendChild(sxSvg);
    imageViewOperate.appendChild(imageViewItemSX);
    
    // 放大
    let imageViewItemFD = createTag("div", [["class", "image-view-item-" + styleId], ["title", "放大"]]);
    let fdSvg = createSvg("m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704m-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64z", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemFD.appendChild(fdSvg);
    imageViewOperate.appendChild(imageViewItemFD);

    // 还原
    let imageViewItemH = createTag("div", [["class", "image-view-item-" + styleId], ["title", "还原"]]);
    let hSvg = createSvg("m160 96.064 192 .192a32 32 0 0 1 0 64l-192-.192V352a32 32 0 0 1-64 0V96h64zm0 831.872V928H96V672a32 32 0 1 1 64 0v191.936l192-.192a32 32 0 1 1 0 64zM864 96.064V96h64v256a32 32 0 1 1-64 0V160.064l-192 .192a32 32 0 1 1 0-64l192-.192zm0 831.872-192-.192a32 32 0 0 1 0-64l192 .192V672a32 32 0 1 1 64 0v256h-64z", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemH.appendChild(hSvg);
    imageViewOperate.appendChild(imageViewItemH);

    // 向左旋转
    let imageViewItemZ = createTag("div", [["class", "image-view-item-" + styleId], ["title", "向左旋转"]]);
    let zSvg = createSvg("M289.088 296.704h92.992a32 32 0 0 1 0 64H232.96a32 32 0 0 1-32-32V179.712a32 32 0 0 1 64 0v50.56a384 384 0 0 1 643.84 282.88 384 384 0 0 1-383.936 384 384 384 0 0 1-384-384h64a320 320 0 1 0 640 0 320 320 0 0 0-555.712-216.448z", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemZ.appendChild(zSvg);
    imageViewOperate.appendChild(imageViewItemZ);
    
    // 向右旋转
    let imageViewItemY = createTag("div", [["class", "image-view-item-" + styleId], ["title", "向右旋转"]]);
    let ySvg = createSvg("M784.512 230.272v-50.56a32 32 0 1 1 64 0v149.056a32 32 0 0 1-32 32H667.52a32 32 0 1 1 0-64h92.992A320 320 0 1 0 524.8 833.152a320 320 0 0 0 320-320h64a384 384 0 0 1-384 384 384 384 0 0 1-384-384 384 384 0 0 1 643.712-282.88z", "#ffffff", [["class","image-view-icon-" + styleId]]);
    imageViewItemY.appendChild(ySvg);
    imageViewOperate.appendChild(imageViewItemY);
    
    imageViewBox.appendChild(imageViewOperate);
    
    // 关闭按钮
    let close = createTag("div", [["class", "image-view-close-" + styleId], ["title", "关闭"]]);
    let closeSvg = createSvg(["M510.976 7.168C231.424 7.168 5.12 233.472 5.12 513.024 5.12 792.576 231.424 1018.88 510.976 1018.88s505.856-226.304 505.856-505.856v-0.512c-0.512-279.552-226.816-505.344-505.856-505.344z", "M735.744 670.72c19.968 17.92 22.016 48.64 4.096 69.12s-48.64 22.016-69.12 4.096l-2.048-2.048-156.672-159.744-156.16 155.648c-19.456 19.456-51.2 19.456-70.656 0-19.456-19.456-19.456-51.2 0-70.656L440.32 510.976 284.672 355.328c-19.456-19.456-19.456-51.2 0-70.656s51.2-19.456 70.656 0L512 447.488l156.16-156.16c19.968-17.92 51.2-16.384 69.12 4.096 16.896 19.456 16.384 48.64-1.536 66.56L580.096 517.12l155.648 153.6z"], ["rgba(0,0,0,0.5)", "#ffffff"], [["class", "image-view-svg-max-close-" + styleId]]);
    close.appendChild(closeSvg);
    imageViewBox.appendChild(close);

    // 左箭头
    let leftArrow = createTag("div", [["class", "image-view-left-" + styleId], ["title", "上一张"]]);
    let leftArrowSvg = createSvg(["M512 938.666667C276.693333 938.666667 85.333333 747.264 85.333333 512S276.693333 85.333333 512 85.333333c235.264 0 426.666667 191.402667 426.666667 426.666667s-191.402667 426.666667-426.666667 426.666667z", "M573.568 692.053333a31.872 31.872 0 0 1-22.613333-9.301333l-148.736-148.053333a32.042667 32.042667 0 0 1 0-45.354667l148.778666-148.138667a31.957333 31.957333 0 1 1 45.141334 45.354667L470.101333 512l126.037334 125.44a32 32 0 0 1-22.613334 54.613333z"], ["rgba(0,0,0,0.5)", "#ffffff"], [["class", "image-view-svg-max-" + styleId]]);
    leftArrow.appendChild(leftArrowSvg);
    imageViewBox.appendChild(leftArrow);

    // 右箭头
    let rightArrow = createTag("div", [["class", "image-view-right-" + styleId], ["title", "下一张"]]);
    let rightArrowSvg = createSvg(["M512 85.333333c235.306667 0 426.666667 191.402667 426.666667 426.666667s-191.36 426.666667-426.666667 426.666667C276.736 938.666667 85.333333 747.264 85.333333 512S276.736 85.333333 512 85.333333z", "M450.432 331.946667c8.149333 0 16.341333 3.072 22.613333 9.301333l148.736 148.053333a32.042667 32.042667 0 0 1 0 45.354667l-148.778666 148.138667a31.957333 31.957333 0 1 1-45.141334-45.354667L553.898667 512l-126.037334-125.44a32 32 0 0 1 22.613334-54.613333z"], ["rgba(0,0,0,0.5)", "#ffffff"], [["class", "image-view-svg-max-" + styleId]]);
    rightArrow.appendChild(rightArrowSvg);
    imageViewBox.appendChild(rightArrow);

    dialog.appendChild(imageViewBox);
    document.body.appendChild(dialog);
    styles();

    // 事件监听
    // 关闭
    close.addEventListener("click", () => {
        dialog.close();
        setTimeout(() => {
            const dialogs = document.getElementById(`dialog_${styleId}`);
            const styleids = document.getElementById(styleId);
            dialogs.parentNode.removeChild(dialogs);
            styleids.parentNode.removeChild(styleids);
        }, 300);
    });

    // 左箭头
    leftArrow.addEventListener("click", () => {
        let length = imgs.length - 1;
        config.currIndex = config.currIndex - 1;
        if (config.loop) {
            if (config.currIndex < 0) {
                config.currIndex = length;
            }
        } else {
            if (config.currIndex < 0) {
                config.currIndex = 0;
                return;
            }
        }
        resetImageState();
        spanCurr.innerHTML = config.currIndex + 1;
        img.src = imgs[config.currIndex];
    });

    // 右箭头
    rightArrow.addEventListener("click", () => {
        let length = imgs.length - 1;
        config.currIndex = config.currIndex + 1;
        if (config.loop) {
            if (config.currIndex > length) {
                config.currIndex = 0;
            }
        } else {
            if (config.currIndex > length) {
                config.currIndex = length;
                return;
            }
        }
        resetImageState();
        spanCurr.innerHTML = config.currIndex + 1;
        img.src = imgs[config.currIndex];
    });

    // 上下翻转（3D效果）
    sxfzSvg.addEventListener("click", () => {
        flipY = flipY === 1 ? -1 : 1;
        updateImageTransform();
    });

    // 左右翻转（3D效果）
    zyfzSvg.addEventListener("click", () => {
        flipX = flipX === 1 ? -1 : 1;
        updateImageTransform();
    });

    // 缩小
    sxSvg.addEventListener("click", () => {
        currScale = currScale - config.curr;
        if (currScale < config.min) currScale = config.min;
        updateImageTransform();
    });

    // 放大
    fdSvg.addEventListener("click", () => {
        currScale = currScale + config.curr;
        if (currScale > config.max) currScale = config.max;
        updateImageTransform();
    });

    // 左旋转
    zSvg.addEventListener("click", () => {
        currRotation = currRotation - 90;
        updateImageTransform();
    });

    // 右旋转
    ySvg.addEventListener("click", () => {
        currRotation = currRotation + 90;
        updateImageTransform();
    });

    // 还原
    hSvg.addEventListener("click", () => {
        resetAll();
    });

    // 重置图片状态（切换图片时使用）
    function resetImageState() {
        img.style.transition = 'none';
        currRotation = 0;
        currScale = 1;
        flipX = 1;
        flipY = 1;
        updateImageTransform();
        img.offsetHeight;
        resetPosition();
        setTimeout(() => {
            img.style.transition = 'all 0.3s ease';
        }, 10);
    }

    // 重置所有状态（还原按钮使用）
    function resetAll() {
        img.style.transition = 'none';
        currRotation = 0;
        currScale = 1;
        flipX = 1;
        flipY = 1;
        offsetX = 0;
        offsetY = 0;
        updateImageTransform();
        img.offsetHeight;
        setTimeout(() => {
            img.style.transition = 'all 0.3s ease';
        }, 10);
    }

    // 打开图片查看器
    dialog.showModal();
};

/**
 * 水印功能 - 固定顶层水印实现（背景图片版本）
 * @param {Object} options - 配置选项
 * @param {HTMLElement} [options.container=document.body] - 水印容器，默认为 document.body
 * @param {string} [options.content="Watermark"] - 水印文本内容
 * @param {Object} [options.style] - 水印样式配置
 * @param {string} [options.style.fontSize="16px"] - 字体大小
 * @param {string} [options.style.color="rgba(0,0,0,0.1)"] - 字体颜色
 * @param {number} [options.style.rotate=-30] - 旋转角度
 * @param {number} [options.style.zIndex=9999] - 层级
 * @param {number} [options.style.width=200] - 单个水印宽度
 * @param {number} [options.style.height=150] - 单个水印高度
 * @returns {Object} 水印控制对象，包含销毁和更新方法
 * 
 * @example
 * 基本使用
 * const watermark = createWatermark({
 *      container: document.querySelector('.app'),
 *      content: '机密文件',
 *      style: {
 *          fontSize: '20px',
 *          color: 'rgba(0, 0, 0, 0.15)',
 *          rotate: -35,
 *          width: 200,
 *          height: 200
 *      }
 * });
 * 
 * // 5秒后更新水印
 * setTimeout(() => {
 *      watermark.updateContent("最终版本");
 * },5000);
 * 
 * // 10秒后销毁水印
 * setTimeout(() => {
 *      watermark.updateContent("最终版本");
 * }, 10000);
 */
function watermark(options = {}) {
    // 默认配置
    const config = {
        container: document.body,
        content: "Watermark",
        style: {
            fontSize: "16px",
            color: "rgba(0,0,0,0.1)",
            rotate: -30,
            zIndex: 2147483647,
            width: 250,
            height: 250,
            lineHeight: 1.5, // 新增行高
            textAlign: 'center' // 新增文本对齐
        },
        ...options
    };
    
    // 合并样式
    const style = {
        fontSize: '16px',
        color: 'rgba(0, 0, 0, 0.1)',
        rotate: -30,
        zIndex: 2147483647,
        width: 250,
        height: 250,
        lineHeight: 1.5,
        textAlign: 'center',
        ...config.style
    };
    
    // 计算文本在旋转后不会超出边界的最大位置
    function calculateSafePosition(textArray, fontSize, lineHeight, rotateAngle, canvasWidth, canvasHeight, isSecondText = false) {
        const tempCanvas = document.createElement('canvas');
        const tempCtx = tempCanvas.getContext('2d');
        tempCtx.font = `bold ${fontSize} Arial, sans-serif`;
        
        // 计算多行文本的总高度
        const textHeight = parseInt(fontSize, 10);
        const totalTextHeight = textHeight * textArray.length * lineHeight;
        
        // 计算最宽文本行的宽度
        let maxTextWidth = 0;
        textArray.forEach(line => {
            const textMetrics = tempCtx.measureText(line);
            maxTextWidth = Math.max(maxTextWidth, textMetrics.width);
        });
        
        // 计算旋转后的文本边界框
        const rad = rotateAngle * Math.PI / 180;
        const cos = Math.abs(Math.cos(rad));
        const sin = Math.abs(Math.sin(rad));
        
        const rotatedWidth = maxTextWidth * cos + totalTextHeight * sin;
        const rotatedHeight = maxTextWidth * sin + totalTextHeight * cos;
        
        // 计算安全边距
        const safeMarginX = rotatedWidth / 2;
        const safeMarginY = rotatedHeight / 2;
        
        if (isSecondText) {
            // 第二个文本在3/4位置
            return {
                x: Math.min(canvasWidth - safeMarginX, canvasWidth * 0.75),
                y: Math.min(canvasHeight - safeMarginY, canvasHeight * 0.75)
            };
        } else {
            // 第一个文本在1/4位置
            return {
                x: Math.max(safeMarginX, canvasWidth * 0.25),
                y: Math.max(safeMarginY, canvasHeight * 0.25)
            };
        }
    }
    
    // 绘制多行文本（支持换行）
    function drawMultilineText(ctx, text, x, y, fontSize, lineHeight, textAlign) {
        const lines = text.split('\n');
        const lineHeightPx = parseInt(fontSize, 10) * lineHeight;
        const totalHeight = lines.length * lineHeightPx;
        
        // 根据对齐方式调整起始位置
        let startY;
        if (textAlign === 'center') {
            startY = y - totalHeight / 2 + lineHeightPx / 2;
        } else {
            startY = y;
        }
        
        lines.forEach((line, index) => {
            const currentY = startY + index * lineHeightPx;
            ctx.fillText(line, x, currentY);
        });
    }
    
    // 生成水印背景图片的base64数据
    function generateWatermarkImage() {
        // 创建canvas绘制水印
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        
        // 设置canvas尺寸
        canvas.width = style.width;
        canvas.height = style.height;
        
        // 清除画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // 设置文本样式
        ctx.font = `bold ${style.fontSize} Arial, sans-serif`;
        ctx.fillStyle = style.color;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        // 将内容按换行符分割
        const textLines = config.content.split('\n');
        
        // 计算两个文本的安全位置
        const firstTextPos = calculateSafePosition(
            textLines, 
            style.fontSize,
            style.lineHeight,
            style.rotate, 
            canvas.width, 
            canvas.height,
            false
        );
        
        const secondTextPos = calculateSafePosition(
            textLines,
            style.fontSize,
            style.lineHeight,
            style.rotate, 
            canvas.width, 
            canvas.height,
            true
        );
        
        // 绘制第一个文本（1/4位置）
        ctx.save();
        ctx.translate(firstTextPos.x, firstTextPos.y);
        ctx.rotate(style.rotate * Math.PI / 180);
        drawMultilineText(ctx, config.content, 0, 0, style.fontSize, style.lineHeight, style.textAlign);
        ctx.restore();
        
        // 绘制第二个文本（3/4位置）
        ctx.save();
        ctx.translate(secondTextPos.x, secondTextPos.y);
        ctx.rotate(style.rotate * Math.PI / 180);
        drawMultilineText(ctx, config.content, 0, 0, style.fontSize, style.lineHeight, style.textAlign);
        ctx.restore();
        
        // 返回base64图片数据
        return canvas.toDataURL('image/png');
    }
    
    // 创建水印容器
    const watermarkDiv = document.createElement('div');
    const id = random(8, "str");
    watermarkDiv.setAttribute('id', id);
    
    // 生成水印图片
    const watermarkImage = generateWatermarkImage();
    
    // 设置水印容器样式
    Object.assign(watermarkDiv.style, {
        position: 'fixed',
        top: '0',
        left: '0',
        width: '100vw',
        height: '100vh',
        pointerEvents: 'none',
        zIndex: style.zIndex,
        backgroundImage: `url("${watermarkImage}")`,
        backgroundRepeat: 'repeat',
        backgroundSize: `${style.width}px ${style.height}px`,
        backgroundPosition: '0 0'
    });
    
    // 添加到容器
    config.container.appendChild(watermarkDiv);
    
    // 窗口大小变化时重新生成水印
    function handleResize() {
        const newWatermarkImage = generateWatermarkImage();
        watermarkDiv.style.backgroundImage = `url("${newWatermarkImage}")`;
        watermarkDiv.style.backgroundSize = `${style.width}px ${style.height}px`;
    }
    
    // 监听窗口大小变化
    window.addEventListener('resize', handleResize);
    
    return {
        destroy: () => {
            window.removeEventListener('resize', handleResize);
            if (watermarkDiv.parentNode) {
                watermarkDiv.parentNode.removeChild(watermarkDiv);
            }
        },
        
        updateContent: (newContent) => {
            config.content = newContent;
            const newWatermarkImage = generateWatermarkImage();
            watermarkDiv.style.backgroundImage = `url("${newWatermarkImage}")`;
        },
        
        updateStyle: (newStyle) => {
            Object.assign(style, newStyle);
            watermarkDiv.style.zIndex = style.zIndex;
            const newWatermarkImage = generateWatermarkImage();
            watermarkDiv.style.backgroundImage = `url("${newWatermarkImage}")`;
            watermarkDiv.style.backgroundSize = `${style.width}px ${style.height}px`;
        },
        
        getConfig: () => {
            return { ...config, style: { ...style } };
        },
        
        getElement: () => {
            return watermarkDiv;
        }
    };
};